Here is the analysis of the leaked GitHub. The analysis of leaked files are completely performed by AI Agent and cross-checked manually to remove any misinformation. The future developments of this case will be updated on this very article in coming days.
INTRODUCTION
Github is being tageted continuously by Threat Actor Groups and Campaigns like Shai-Hulud, TeamPCP, Lazarus, Bluenoroff etc. One of the reason to make it as a hot-bed is the scope of large scale Supply Chain Attack that spirals down and infect more packages.

On 19th May, 2026, TEAMPCP had advertised a post on Breach Forum regarding the Internal Source of GitHub.

As per the claim, there are about 4K private code repositories listed in the leak. The post also encompasses 5 screenshots as proof of data.
WHAT’S INSIDE
TeamPCP had shared 2 links on LimeWire which will get expired in 7 days:-
- github-repos.txt
- samples.zip
The 283KB text file consists of various GitHub projects, which is hosted here.

By checking the timeline of the Github Repos, we can estimate the list has been dumped starting on May 18, 2026 which spans toll May 19, 2026.
SAMPLES.ZIP
This zipped folder consists of 2 Ruby files namely:-
- organizations_controller.rb
- pull_requests_controller.rb
Here, we are going to analyze both Ruby files in depth (assisted with AI).
organizations_controller.rb
NUTSHELL: A leaked Rails controller reveals how GitHub enforces OFAC sanctions, handles enterprise trials, protects org deletion, and quietly tracks every Copilot checkbox — all in one 562-line file.
Every time someone creates a GitHub organization, a single Rails controller does the heavy lifting. OrganizationsController — 562 lines of Ruby tucked inside GitHub’s monolith — orchestrates plan selection, billing validation, trade compliance screening, CAPTCHA verification, and post-creation analytics, all before redirecting the new admin to their invite page. A close read of this file surfaces a surprising amount of how GitHub actually works, as opposed to how it presents itself publicly.
What follows is a structured analysis of every significant pattern in the file: the plan hierarchy, OFAC compliance, CAPTCHA strategy, org deletion mechanics, billing flow, database topology, Copilot instrumentation, and one quietly persistent typo.
➤THE PLAN HIERARCHY
GitHub’s marketing copy refers to “Free,” “Team,” and “Enterprise Cloud.” The code uses different names entirely. Inside org_hash[:plan], the valid identifiers are:

The cloud trial path is the most interesting. When params.dig("enterprise", "plan") == "cloud-trial" and org_hash[:plan] == "business_plus", GitHub does not actually create a paid organization. It substitutes the free plan, creates the org normally, then retrospectively patches it into a trial state:
params: cloud-trial + business_plus → plan_name = free → org created free → EnterpriseCloudTrial.create → trial notifications sent
This decouples trial provisioning from payment collection, letting GitHub start trials without a billing instrument on file. The actual trial limits and expiry logic live in Billing::EnterpriseCloudTrial, not here.
Seat cap is a remote configurable
For paid plans, there is a hard cap on seats-at-creation enforced against Configurable::SeatLimitForUpgrades::DEFAULT_SEAT_LIMIT_FOR_UPGRADES. The value isn’t hardcoded — it’s drawn from a Configurable, which GitHub can adjust at runtime without a deploy. Requests over the cap receive a flash error and are bounced back to the plan selection page.
➤OFAC & TRADE COMPLIANCE
Sanctions enforcement appears at three separate points in the controller, not just one. This layered approach means a flagged user can be caught at any stage of the funnel:
before_action :check_trade_compliance -> only: new/create, if: couponedhas_any_trade_restrictions? && plan.paid? -> flash error + dogstats:rejectedrequire_plan_selection -> OFAC users → free plans only
NOTE: Free plan creation is explicitly allowed for OFAC-flagged users. The gating condition is always
plan.paid?. Flagged users can create free organizations; they simply cannot access paid tiers at any point in the flow.
The couponed upgrade check (check_trade_compliance fires only when params[:coupon].present?) is treated as its own paid-upgrade vector requiring separate compliance review. This suggests the engineering team considered coupon redemption a possible sanctions bypass route and added the before-action as a separate guard.
When a flagged user is blocked mid-create, the event is not silently dropped. A Datadog metric fires: organization.plan_selection action:rejected plan:X. This gives GitHub’s trust and compliance team visibility into attempted paid signups from restricted accounts.
“Free plan creation is explicitly allowed for OFAC-flagged users. The gating condition is always plan.paid?”
➤CAPTCHA STRATEGY
GitHub’s CAPTCHA implementation here is more targeted than a blanket “prove you’re human” gate. The entire Octocaptcha block is wrapped in a condition:
if !plan.paid? && !current_user.hammy? precheck = Octocaptcha.new(session, page: :org_create, user: current_user) if precheck.show_captcha? # full verification path... endend
Two conditions must both be false to trigger CAPTCHA: the plan must be free, and the user must not be hammy?. Paid signups skip it entirely — the billing instrument acts as the human verification. The hammy? flag marks internal/employee accounts and other trusted users who bypass CAPTCHA unconditionally.
2-STAGE CHECK
Rather than immediately verifying a CAPTCHA token on every free org creation, the code runs a precheck first: precheck.show_captcha?. Only if the precheck decides captcha should be shown does it proceed to full token verification. This avoids unnecessary network round-trips to the Octocaptcha service for users who aren’t flagged.
BROWSER LOAD FAILURE PATH
If the frontend reports that the CAPTCHA script failed to load (params[:error_loading_captcha]), the error is reported to Failbot under the octocaptcha-errors app tag, a counter is incremented in Datadog, and the timeout is extended via Octocaptcha::HIGHER_BROWSER_LOAD_TIMEOUT. This is a graceful degradation path — CAPTCHA load failures don’t kill the org creation attempt outright.
➤ORGANIZATION DELETION
Deletion is deceptively complex. The surface API is a single destroy action, but under it sits a multi-layer guard system.
DANGER ZONE TOKEN
DeleteToken.verify!(current_user, current_organization, params[:dangerzone]) acts as a CSRF-like gate specific to destructive operations. If verification fails, a DeleteToken::DangerZone exception is raised, caught in a rescue block, and reported to Failbot. Critically, the rescue does not halt further execution — control falls through to the ensure block, which redirects the user to / regardless of outcome.
HARD BLOCKERS
Before async destruction begins, cannot_delete_reason is checked on the model. Two reasons have explicit flash messages:
- :trusted_oauth_apps_owner — The org owns OAuth applications that other users have trusted. The org cannot be deleted until those apps are removed or transferred to another owner.
- :sponsorable — The org has an active GitHub Sponsors profile. It must be explicitly unpublished before deletion is allowed.
Any other reason returned by the model falls through to the else clause, and deletion proceeds. This means the model can return additional reasons, but the controller will silently ignore them and destroy the org anyway — a potential gap if new blockers are added at the model layer without a corresponding controller update.
ASYNC DESTRUCTION
When deletion clears all guards, current_organization.async_destroy(current_user) fires. The org is not torn down synchronously. The user sees “is being deleted” in a flash notice and is redirected. Background jobs handle the cascade: repositories, memberships, billing subscriptions, and everything else. This is the only sensible approach given the scale of data involved.
NOTE: Trade-restricted orgs set
flash[:trade_controls_organization_billing_error] = trueduring deletion, but this does not block the deletion itself. It surfaces a UI message only.
➤THE BILLING FLOW
The most architecturally interesting section of the controller is the billing collection flow, because it has to handle a fundamental problem: billing information is collected before the organization exists, so there’s nothing to attach it to yet.
SESSION AS TEMP LEDGER
billing form submitted -> address validated -> timestamp → sessionorg created -> timestamp merged into hash -> session key deleted
The billing_address_validated_at timestamp is stashed in the session after address validation, then read back and merged into the billing hash when the org is actually created. The comment in the code explicitly notes this approach: the org doesn’t exist yet, so the associated account screening profile doesn’t exist, so the validation timestamp has nowhere to live except the session.
STANDARD VS CORPORATE TERM SPLIT
Billing handling diverges based on the terms of service type the user is signing up under. Standard terms users — individuals creating orgs for personal or small-team use — have their billing info saved directly to the current user’s billing contact, since that’s what the org will inherit. Corporate / GitHub Customer Agreement users get a freshly constructed Billing::Contact object validated for entity-level trade screening. VAT code validation runs separately through Customer#validate_vat_code and has its own flash key.
ADDRESS FAILURE UX
When address validation fails, the controller strips the country_code query parameter from the redirect URI before bouncing the user back. This is intentional: the missing required field causes the form to re-render in edit mode. Query parameters are being used as ephemeral UI state — a pattern that’s brittle but requires no server-side storage.
➤DATABASE CLUSTER TOPOLOGY
The depends_on_clusters declarations make the database architecture partially visible. The show action — rendering an org dashboard — touches nine separate clusters:

NOTE: The Copilot cluster is the only optional dependency.
depends_on_clusters ApplicationRecord::Copilot, optional: true— this means the org dashboard and signup page will load even if the Copilot cluster is unavailable. All other cluster failures are presumably hard failures that prevent the action from running.
The absence of Configurations from the new action is telling: feature flags aren’t consulted during signup form rendering, only during the active dashboard view. This makes sense — you wouldn’t want a feature flag outage to block new org creation.
COPILOT FUNNEL INSTRUMENTATION
Every successful organization creation fires a GlobalInstrumenter event tracking whether the Copilot add-on checkbox was checked:
GlobalInstrumenter.instrument( "analytics.event", category: "new_org_copilot_add_on", action: "create_free_org", label: "copilot_box_checked:#{add_on_checked};")
This fires unconditionally — whether the box is checked or not. The data tells the Copilot growth team the exact rate at which new org creators see the add-on checkbox and convert, enabling A/B testing of placement, copy, and default state.
SESSION FLAGS FOR MULTI-STEP CONTINUATION
When the checkbox is checked, two session flags are set: copilot_flash_create_org_message and copilot_flash_pay_info_message. These are read at subsequent steps in the Copilot business signup flow to show contextual banners — a lightweight way to carry state across a multi-page funnel without touching the database.
CLASSROOM USERS ARE EXEMPT
Users arriving from classroom.github.com are redirected to the classroom host immediately after org creation. The Copilot add-on session state is never set for this path. Classroom is treated as a completely separate funnel that exits the standard post-creation flow entirely.
➤THE TYPO REVELATION
Line 344, inside the rescue block for failed org deletions:
failbot StandardError.new( "OrganizationsController.destroy failed - invalid CRSF token")
NOTE: It says CRSF, not CSRF. This is the error string that gets reported to Failbot whenever a deletion fails due to an invalid danger zone token. Engineers debugging via Failbot would need to search for “CRSF” — not the standard “CSRF” — to find these events. The code functions correctly; the error message is purely mislabeled.
The persistence of this typo tells you something: DeleteToken::DangerZone failures are rare enough that nobody has had to search for this string in Failbot often enough to notice the transposition. High-traffic error messages get corrected quickly because engineers search for them constantly. Rare ones linger.
ANOTHER INCONSISTENCY
Line 474 disables a rubocop rule with rubocop:todo, but line 478 re-enables it with rubocop:enable rather than rubocop:todo. Technically valid rubocop syntax, but semantically inconsistent — enable is for disable/enable pairs, while todo pairs with enable too. The inconsistency won’t cause failures, but it would confuse a developer trying to understand which suppression style is in use.
➤CONCLUSION
A 562-line Rails controller is never just a controller. OrganizationsController is a window into GitHub’s product priorities: Copilot growth is tracked at every org creation, OFAC compliance is layered three deep, billing collection precedes object existence and therefore requires session gymnastics, and the database topology for a single dashboard view fans out across nine clusters. The optional Copilot cluster dependency suggests that team is still building infrastructure muscle and needs resilience gates that older, more established systems don’t require.
The CRSF typo is the most human detail in the file — a small, invisible error in a rarely-exercised code path, surviving because the system works well enough that nobody has had to look for it.
pull_requests_controller.rb
This is a 3,429-Line Controller running every GitHub Pull Requests.
NUTSHELL: This reveals a distributed system held together by 27 database clusters, six distinct rate limiters, a graceful merge timeout handler, a secret PR stacking feature, a “Voltron” timeout framework, and a Copilot findings tab gated behind a feature flag.

Every pull request viewed, merged, reverted, or commented on at GitHub is processed by one file: PullRequestsController. At 3,429 lines, it is not so much a controller as an operating system for the world’s largest software collaboration platform. It orchestrates 27 database clusters, coordinates 4 different JavaScript bundles, enforces six distinct rate limiting rules, and holds a growing number of features in various states of rollout. Reading it carefully reveals not just how GitHub works, but how it’s changing.
What follows is a structured analysis of every significant system in the file: the staggering database topology, the merge pipeline, the grace-timeout “Voltron” framework, Copilot’s deepening integration, the secret PR stacking feature, anonymous rate limiting via TLS fingerprinting, the changes route migration, the post-merge split, and the bully rejection guard.
➤DATABASE TOPOLOGY
No single section of this file is more revealing about GitHub’s infrastructure than the cluster dependency declarations. Between lines 133 and 582, the controller declares required and optional database clusters for nearly every action. The result is a map of GitHub’s distributed data architecture, visible just by counting.
THE SHOW ACTION’S HARD DEPENDENCIES
Loading a single PR page touches 13 hard-required clusters — ones that will return a 500 error if unavailable. The comment above this block is unusually direct:
# By adding a cluster to this list, you are asserting that the# Pull Request page should respond with a 500 error when that# cluster is unavailable. Those kinds of changes should not be# made without talking with the Pull Requests team first.depends_on_clusters( ApplicationRecord::Billing, ApplicationRecord::Collab, ApplicationRecord::Configurations, ApplicationRecord::Iam, ApplicationRecord::IamAbilities, ApplicationRecord::InProductTargeting, ApplicationRecord::IssuesPullRequests, ApplicationRecord::Mysql1, ApplicationRecord::NotificationsEntries, ApplicationRecord::Permissions, ApplicationRecord::Repositories, ApplicationRecord::RepositoriesPushes, ApplicationRecord::Spokes, optional: false, only: [:show])
The warning is a rare explicit acknowledgment in code that architecture decisions have uptime consequences. The InProductTargeting cluster — which almost certainly drives feature flags and in-product banners — being a hard dependency means a targeting service outage takes down the PR page entirely.

The Copilot signal: Across every single action that declares it, Copilot is always
optional: true. The cluster shows up in show, files, commits, changes, checks, dashboard, edit_form, linked_closing_reference, resolve_conflicts, open_with_menu, and more — but never as a hard dependency. This is the infrastructure equivalent of a “not load-bearing yet” sign.
LINKED_CLOSING_REFERENCE is the most connected action!
The small endpoint that renders the “closes #123” reference sidebar item declares the most clusters of any single action: 13 hard and 1 optional. This suggests it makes a remarkable number of data joins — issues, pull requests, repositories, IAM, notifications, Memex, Spokes, and more — just to render a single sidebar widget. A classic case of hidden complexity behind a simple-looking feature.
➤MERGE PIPELINE
The merge action is the most consequential in the file. Its design reveals a lot about how GitHub balances safety, user experience, and distributed system constraints.
METHOD SELECTION & FALLBACK CHAIN
Merge method resolution follows a deliberate priority order:
params[:squash_commits] == "1" → squashparams[:do].present? → use params[:do]merge_commit.allowed? → merge else squash (default)
The legacy squash_commits=1 parameter still works in 2026. It’s presumably from an older API surface that predates the do param, kept alive for backward compatibility.
STICKY MERGE METHOD
After a successful merge, the chosen method is saved as the user’s sticky preference for that repository via set_sticky_merge_method. This persistence happens in a separate begin/rescue block after the merge itself — failure to save the preference is silently reported to Failbot but never surfaced to the user. The merge result is more important than the preference save.
THE POST_MERGE SPLIT
Architecture note: Renders don’t happen inside the
mergeaction. On a successful XHR merge, the action redirects to a separatepost_mergeendpoint in JSON format. The comment explains why: “to reduce the likelihood of timeouts, and to avoid sending SELECT queries to cluster primaries.” Separating write (merge) from read (render) is a deliberate distributed systems decision — the primary DB handles the merge commit, then the replica handles the subsequent reads for the UI update.
The post_merge response rebuilds four page fragments simultaneously: timeline, sidebar, merge button, and the PR tab counter in the repo header. All four are rendered server-side as HTML strings, then returned as a single JSON payload for the frontend to stitch back in — a hybrid server-render-and-patch approach rather than a full page reload or a fully client-side update.
TIMEOUT HANDLING: THE RESCUE_FROM BLOCK
The very top of the file (lines 26–49) registers a global timeout rescue specifically for the merge action:
rescue_from_timeout_without_replay only: [:merge] do GitHub.dogstats.increment("pull_requests.merge_timeout_rescued") orchestration = PullRequests::Orchestrations::Merge.active .find_by(pull_request_id: @pull&.id) orchestration&.end_orchestration(:failed, "merge timed out") render_update_content_json({ merging: ... timeout error partial ... }, status: :gateway_timeout)end
Three things are happening here. First, the timeout is tracked in Datadog. Second, any active merge orchestration is explicitly terminated — this prevents ghost orchestrations that would make the PR appear stuck. Third, the UI gets a partial re-render with a retryable error state rather than a blank 504 page. The unretryable: false flag means the button re-appears, not a dead end.
➤VOLTRON: THE TIMEOUT FRAMEWORK
Lines 601–612 declare a constant array called SHOW_FEATURES — a list of feature flags preloaded for the PR show action. Buried in this list are nine entries that reveal an internal framework called “Voltron”:
SHOW_FEATURES = [ # ... other features ... :prs_voltron_graceful_timeout_nine, :prs_voltron_graceful_timeout_eight, :prs_voltron_graceful_timeout_seven, :prs_voltron_graceful_timeout_six, :prs_voltron_graceful_timeout_five, :prs_voltron_graceful_timeout_four, :prs_voltron_graceful_timeout_testing, :prs_defer_participants, :prs_overview_react,]
Voltron is GitHub’s internal name for a graceful timeout framework on the PR page — the numbered flags suggest different timeout thresholds being tested across segments of traffic.
The numbered suffixes (four through nine) strongly imply that each flag corresponds to a different timeout threshold, tested against different user segments simultaneously. Rather than a single global timeout value, GitHub is running what amounts to a continuous A/B test on how long the PR page is allowed to take before degrading gracefully. The _testing variant is presumably a canary bucket. This is timeout-as-a-feature-flag — a sophisticated way to tune performance thresholds without deploys.
➤PR STACKING
Lines 1113–1139 contain a complete implementation of PR stacking — a feature that lets users chain pull requests on top of each other:
def add_new_pull_request_to_stack(new_pull) return unless PullRequests::Stacks.enabled?(current_repository) previous_pull = PullRequest.open_pulls.find_by( repository: current_repository, head_ref: new_pull.base_ref, ) result = PullRequests::Stacks.create_or_append(bottom: previous_pull, top: new_pull) # ...end
Stacking is triggered by params[:create_stack] == "1" during PR creation. The logic finds an open PR whose head_ref matches the new PR’s base_ref — i.e., the PR immediately below in the chain — and calls Stacks.create_or_append. If no qualifying PR is found, a flash error says “Cannot find another PR to build a stack with.” The feature is gated behind PullRequests::Stacks.enabled?(current_repository), making it opt-in per repository. It’s present in the controller but clearly not yet universally available.
➤COPILOT’S EXPANDING FOOTPRINT
Copilot appears in this file in three distinct roles, each at a different stage of production readiness.
FINDINGS TAB
Lines 1599–1615 define a findings action — a new PR tab dedicated to Copilot’s code review output:
def findings unless FeatureFlag.vexi.enabled?(:copilot_code_review_findings_ui, current_user, default: false) return redirect_to gh_show_pull_request_path(@pull) end override_analytics_location "///pull_requests/show/findings" render_pull_requests_react(pull: @pull)end
Anyone without the copilot_code_review_findings_ui flag enabled is redirected to the standard PR view. The tab exists in the navigation but is invisible to most users. Unlike other tab actions, findings has the rubocop disable comment (not todo) — suggesting it was intentionally exempted from the RESTful action rule, not just deferred.
SWE AGENT IN THE DASHBOARD
The dashboard action passes a new local variable to the view:
swe_agent_enabled: Copilot::Public::User.for(T.must(current_user)).swe_agent_enabled?
This surfaces whether the current user has GitHub’s SWE agent — an autonomous coding assistant — enabled, presumably to show or hide related UI controls on the PR dashboard. Its presence in a production controller method (not a flag check) suggests it’s beyond early experiment stage.
CODING GUIDELINES AS A SHOW-PAGE FEATURE FLAG
:copilot_coding_guidelines appears in the SHOW_FEATURES preload list. This feature — Copilot learning from a repo’s coding style to guide reviews — is preloaded on every PR page view for users who have it enabled. Its presence in the preload list means it influences the initial render, not a deferred load.
➤ANONYMOUS RATE LIMITING VIA TLS FINGERPRINTING
The patch action (which serves raw .patch files) is rate limited for unauthenticated users. The rate limit key construction at lines 2968–2973 reveals a clever technique:
def patch_action_rate_limit_key key_base = "#{self.class.to_s.underscore}:#{action_name}" actor_identifier = request.env.fetch("HTTP_X_SSL_JA3_HASH", nil) actor_identifier = request.remote_ip if actor_identifier.blank? "#{key_base}:#{actor_identifier}"end
JA3 fingerprinting:
HTTP_X_SSL_JA3_HASHis a TLS fingerprint — a hash derived from the TLS handshake characteristics of the client connection (cipher suites, extensions, elliptic curves). JA3 fingerprints are stable across IP rotations for a given browser or tool. GitHub uses this as the rate limit key for anonymous patch requests, falling back to IP only if no JA3 hash is available. This makes the rate limiter significantly harder to bypass with simple IP rotation — you’d need to change your TLS stack, not just your proxy.
The patch_action_request_is_rate_limited? predicate simply returns !logged_in?. Authenticated users are exempt entirely; anonymous scrapers get JA3-keyed rate limiting.
CHANGES ROUTE MIGRATION
Lines 3357–3427 implement a transparent bidirectional redirect system between three overlapping routes: /files, /commits, and the new /changes.
case action_namewhen "files" # files → changes (when feature flags enabled) if changes_route_enabled redirect_url = range.present? ? "#{base_path}/changes/#{new_range}" : "#{base_path}/changes" endwhen "changes" # changes → files/commits (when feature flags disabled) unless changes_route_enabled redirect_url = range.include?("..") ? "#{base_path}/files/#{range}" : "#{base_path}/commits/#{range}" endend
The logic is bidirectional: users with the unified_changes_route_enabled? flag are transparently redirected from /files and /commits to /changes; users without it are redirected back from /changes to the legacy routes. Both paths preserve all query parameters via append_changes_redirect_query_params.
Range format intelligence: When deciding whether a URL goes to
/filesor/commitson the fallback path, the code inspects the range string. A range containing..(e.g.,abc123..def456) goes to/files. A single OID without dots goes to/commits. The format of the range string encodes semantic information about what kind of view was intended.
Redirects are also tagged for telemetry via override_action_tag_for_redirect — so the redirect itself doesn’t pollute the timing metrics of the target action. The redirect shows up in Datadog as files_redirect, not as a slow files request.
➤BULLY REJECTION GUARD
The reject_bully? method at lines 2796–2803 is one of the more human-readable pieces of code in the file:
def reject_bully?(pull = nil) return false if current_user_can_push? if blocked_by_owner? || (pull && blocked_by_author?(pull.user)) flash[:error] = "You can't perform that action at this time." redirect_to current_repository.permalink true endend
This method is called at the top of both create and comment — preventing blocked users from creating new PRs or commenting on existing ones. Push access bypasses it entirely: maintainers are never blocked even if they’ve been blocked by another user. The check is directional — blocked_by_owner? checks if the repo owner has blocked the current user, and blocked_by_author? checks if the PR’s author has blocked them. A collaborator blocked by a PR author can’t comment on that author’s PR. The error message is deliberately vague — it doesn’t reveal why the action is unavailable.
➤AUTHORIZATION MATRIX
The before-action declarations at lines 52–113 form an authorization matrix that reveals which actions are protected and how. Several patterns stand out.
DASHBOARD AND SHOW_MENU_CONTENT SKIP AUTHENTICATION
skip_before_action :authorization_required, only: %w(dashboard show_menu_content)
The PR dashboard at /pulls doesn’t require login — it’s accessible as a public page. show_menu_content similarly skips authorization, relying instead on the template allowlist (VALID_SHOW_MENU_CONTENT_TEMPLATES) to prevent arbitrary partial rendering.
ROBOTS GET 484 FOR LABEL/MILESTONE QUERIES
if robot? && label_or_milestone return render_404end
Bots requesting the PR index with label or milestone filters are served a 404. This prevents scrapers from enumerating issues through filtered queries — it’s a soft anti-scraping measure that relies on user-agent detection.
PAGINATION ONLY CAPPED FOR BOTS
skip_before_action :cap_pagination, unless: :robot?
Human users skip pagination capping — the cap only applies to automated clients. This lets GitHub impose result limits on scrapers without affecting the experience for logged-in humans navigating large PR lists.
REPLICA ROUTING IS CAREFULLY SCOPED
create, update → Repositories replicascreate, comment, update → Mysql1 (user cluster) replicas create only → Collab replicas
Write actions are routed to read replicas for all lookups that don’t require the primary. Three separate prepend_around_action calls scope this per cluster type. The separation means a Collab cluster replica lag won’t affect comment posting, only PR creation.
➤FEATURE FLAG PRELOAD SYSTEM
The SHOW_FEATURES constant lists 22 feature flags preloaded before the show action renders. The variety is a cross-section of active GitHub engineering projects in 2025–2026:

NOTE: The proliferation of
:prx_*flags confirms that GitHub is in the middle of a significant PR page rewrite — ”PRx” appears to be the internal project name for the next-generation pull request UI, being rolled out incrementally per flag.
➤APPLY SUGGESTIONS PIPELINE
The apply_suggestions action (around line 2686) runs a multi-step pipeline for applying reviewer-suggested code changes directly to a branch. The error handling reveals the full failure surface:
parse suggestion JSON → look up review comments → ApplySuggestedChange.call → flash: "Suggestions applied"
Three specific errors are rescued with status codes: NotFoundError (404), ForbiddenError (403), and UnprocessableError (422). A fourth catch-all rescues GitHub::JSON::ParseError and an internal BadSuggestionError, both returning a generic 422. The success flash message pluralizes correctly: “1 Suggestion” vs “3 Suggestions successfully applied” — a small detail that suggests this path is well-tested.
➤DEFERRED LOADING ARCHITECTURE
The file reveals that GitHub defers loading of two specific types of data that used to be part of the initial page render:
# Override AbstractRepositoryController#defer_commit_badges?def defer_commit_badges? trueend# Override AbstractRepositoryController#defer_status_check_rollups?def defer_status_check_rollups? trueend
Commit signature badges and CI status rollups are both loaded asynchronously, post-render. The deferred_commits_data action handles the latter — it fetches commits 10 at a time (COMMITS_TO_FETCH_DATA_FOR_AT_A_TIME = 10), returning a JSON payload with a loadMore flag. The PR page loads and shows commits quickly; their verification badges and CI states trickle in after. This is a deliberate performance trade-off: perceived speed over completeness.
➤CONCLUSION
At 3,429 lines, PullRequestsController is a living archaeology of GitHub’s engineering priorities. Its cluster declarations map the distributed data architecture that makes a single page view possible. Its Voltron flags reveal a sophisticated approach to timeout experimentation. Its stacking feature previews a capability still in rollout. Its JA3 fingerprinting shows a security team thinking beyond IP-based controls. And its proliferating :prx_* flags signal that the PR page most users see today is already being quietly replaced.
The most telling detail may be the simplest: the warning comment on the show action’s cluster list. “Those kinds of changes should not be made without talking with the Pull Requests team first.” In a monolith of this scale, the social architecture — who owns what, who you talk to before changing a dependency — matters as much as the technical one.
github-repos.txt
It’s a snapshot of GitHub’s internal R&D as “internal GitHub repositories” that have been leaked or exposed. This appears to be a significant data leak containing GitHub’s private/internal code repositories.
This file contains thousands of GitHub’s internal private repositories, totaling approximately 283,349 characters of file listings. The repositories were extracted on May 18, 2026.
- Scaling infrastructure (Actions, compute engines, runners)
- Pioneering AI safety and automation (agentic workflows, vulnerability detection)
- Doubling down on accessibility (bots, audits, scorecards)
- Branding and marketing like code, versioning everything
It’s like seeing the blueprint of how GitHub is evolving into a platform that’s not just about hosting code, but about governance, automation, and AI-driven development.
- Accessibility projects Tons of archives like
accessibility-audit-guide.tar.gz,accessibility-scorecard.tar.gz, and evenaccessibility-alt-text-bot.tar.gz. This suggests a huge push to automate accessibility compliance and testing across GitHub. - Actions infrastructure Files like
actions-runner-admin.tar.gz,actions-compute-engine.tar.gz, andactions-network-gateway.tar.gzpoint to deep work on scaling and securing GitHub Actions runners. It looks like they’re experimenting with larger runners, caching, and even OIDC gateways. - AI initiatives Archives such as
ai-research-and-storytelling.tar.gz,ai-safety-responsibility-repos.tar.gz, andai-vulnerability-detection.tar.gzshow GitHub is investing in AI governance, safety, and applied AI tools. There’s evenai-for-everyone-app.tar.gz— sounds like an internal app to democratize AI usage. - Agentic workflows Multiple repos like
agentic-workflows.tar.gz,agentic-security-memory.tar.gz, andagentic-app-creation-react.tar.gzhint at experiments with autonomous agents and workflow orchestration. This is cutting-edge stuff in AI automation. - Brand and marketing repos Files like
brand-marketing-design.tar.gz,brand.github.com.tar.gz, andbrand-experience.tar.gzsuggest GitHub’s design/marketing teams keep their assets versioned just like code. - Security and authorization Archives such as
authorization-platform.tar.gz,advanced-security-field.tar.gz, andartifact-attestations-workflows.tar.gzshow heavy investment in securing the platform and supply chain integrity.
Thousands of GitHub’s internal private repositories in compressed tar.gz format, including:
- Copilot internal projects: copilot-abuse, copilot-api, copilot-chat, copilot-metrics, copilot-agent-runtime, copilot-custom-model, etc.
- CodeQL internal tools: codeql-docs, codeql-team, code-scanning repositories
- Internal infrastructure: database-infrastructure, datacenter-operations, compute-foundation, observability tools
- Internal GitHub services: github.tar.gz (the main monolith), github-chatops, internal-developer.github.com
- Security tools: secret-scanning, security-center, security-operations
- Employee systems: hubber-handbook, hubber-map, IT engineering tools
- Business operations: sales-analytics, customer-success, marketing repositories
- Product development: codespaces, actions, dependabot internal code

Here is the Security & Vulnerability Impact

Business Exposure

LEAKED IMAGES AS PROOF OF HACK
TeamPCP has also attached 4 Images on the post which we will be diving into:-
IMAGE 1:

Billing / VAT / Address Validation Logic
This is likely from OrganizationsController or a billing/signup flow:
- VAT handling is special-cased: VAT codes are pulled from params but not stored on the billing contact in some flows (user_billing_information_hash.delete(:vat_code)). They do client-side re-rendering tricks if VAT validation fails.
- Strict validation before organization creation: Address must be valid, billing email required. They have separate flows for “standard terms of service” vs enterprise/”trade screening”.
- Comments reveal timing quirks: “The organization will only be created after the billing information is confirmed… not at this stage.”
- Error messages like “Billing information has to be valid before proceeding.” and specific VAT errors.
GitHub has internal “trade screening” logic (probably sanctions/export control checks) tied to billing. Organizations on standard plans reuse the user’s personal billing info.
IMAGE 2:

Organization Lifecycle & Danger Zone
- Plan selection logic with per-seat pricing models (monthly/annual, Business Plus, coupons, etc.).
- Organization deletion (def destroy) has a “Danger Zone” protection using DeleteToken.
- Special blocks for: Trusted OAuth apps owner, Sponsorable organizations (must unpublish profile first)
- Analytics events and GA tracking on creation.
NOTE: This is explained in the above code.
IMAGE 3 & 4


The Monolith — Scale is Insane
The ls app/* -a shows hundreds of API resources. Highlights:
Enterprise / Security Heavy Features:
enterprise_advanced_security.rb, enterprise_code_scanning.rb, enterprise_secret_scanning.rbx
enterprise_dependabot_*, enterprise_runner_*
organization_code_scanning_dismissal_requests.rb, repository_secret_scanning.rb, etc
Fine-grained permissions, custom roles, OIDC, SCIM
Copilot Everywhere:
- copilot.rb
- copilot_coding_agent.rb
- copilot_for_business.rb
- copilot_spaces_*
Other Notable Files:
- blackbird.rb (internal file)
- dependabot
- secret_scanning
- vulnerability_alerts
- organization_actions_secrets.rb
- repository_secrets.rb
- Lots of *_rate_limiting
- actions_*, workflows
This confirms GitHub’s architecture is a massive single Rails app with thousands of model/controller files handling everything from repo metadata to AI features to enterprise compliance.
TEAMPCP PRESENCE ON DARKWEB
Following the Session ID and TOX; it is found that the socials shared by the Threat Actor also pilots another project CypherForce Ransomware, as the same socials are shared for it as well.
The group is also active on Telegram.

They are also available on DarkWeb with the contacts listed on their Website with a tagline “The Cats Hijacking Your Supplychains”.
- 22evxpggnkyrxpluewqsrv5j4jtde6hut2peq3w44d6ase676qlkoead.onion

A LOOK-ALIKE DOMAIN REGISTRATION
It is important to note that a look-alike domain of Github has been registered on May 16, 2026.
git-service.com
This domain was used by TeamPCP in compromising DurableTask, which is the official Microsoft Python client for the Durable Task workflow execution framework.
2 malicious files (which are not yet flagged) had been found during the investigation:-
MD5: 907a5a883877808218686bc24b7add65

MD5: b0e85aaafbd37dcaccc6ee734270ebbe
Both these files are seen on 19th May 2026, which also aligns with the Github Leak date.
CONCLUSION
Github tweeted today as they are investigating the case and we can expect a resolution soon!
However, it seems TeamPCP is not going to stop anytime soon!!!
Follow me on Twitter for interesting DarkWeb/InfoSec Short findings!
Leave a Reply