On April 28, Wiz Research published the writeup for CVE-2026-3854, a command injection vulnerability in GitHub’s internal git push pipeline that let any authenticated user execute arbitrary code on GitHub.com’s backend — and on every unpatched GitHub Enterprise Server instance — with a single git push command. GitHub patched GitHub.com itself within hours of the March 4 report. Enterprise Server patches shipped on March 10. Forty-nine days later, when the embargo lifted, 88% of Enterprise Server instances were still on vulnerable versions.

If you operate a GitHub Enterprise Server, stop reading this and check your version. Patched releases are 3.14.25, 3.15.20, 3.16.16, 3.17.13, 3.18.8, 3.19.4, and 3.20.0 (or any later patch in those lines).

What Happened

The flaw lives in babeld, GitHub’s internal git proxy that sits between the public-facing git endpoints and the downstream gitrpcd service that actually executes git operations on storage nodes. When a user runs git push -o some_option=value, those --push-option strings are arbitrary text that the client can set freely. babeld packages them into an internal HTTP-style header called X-Stat, encoding each one as a numbered field — push_option_0, push_option_1, and so on — alongside other operational metadata in a single semicolon-delimited string.

The bug is exactly what it sounds like. babeld copied push option values into the X-Stat header verbatim, without escaping or rejecting the semicolon character. gitrpcd parsed X-Stat with last-write-wins semantics. So a push option containing ;rails_env=development didn’t just sit there as a string — it injected a brand-new key/value pair into the downstream header, overriding whatever the legitimate sender had set.

Wiz chained three injected fields into a working RCE:

  1. rails_env set to a non-production value to break out of the production sandbox that normally prevents arbitrary command execution.
  2. custom_hooks_dir redirected to an attacker-controlled path on shared storage — typically a path inside a repository the attacker themselves had pushed to.
  3. repo_pre_receive_hooks pointed at a crafted hook entry whose path traversal landed on an arbitrary executable.

When gitrpcd then ran the pre-receive hook for the push, it executed the attacker’s binary as the git service user on a backend node shared across millions of repositories.

Technical Details

CVE: CVE-2026-3854 CVSS Base Score: 8.7 (High) — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N CWE: CWE-77 (Improper Neutralization of Special Elements used in a Command) Affected: GitHub.com (pre-March 4 patch); GitHub Enterprise Server prior to 3.14.25 / 3.15.20 / 3.16.16 / 3.17.13 / 3.18.8 / 3.19.4 / 3.20.0 Reported: March 4, 2026 (Wiz Research) GitHub.com fix: March 4, 2026 (same day) GHES patches: March 10, 2026 Public disclosure: April 28, 2026

The attack precondition is minimal: any authenticated user with push access to any repository on the instance. On GitHub.com that meant any GitHub user, since you can push to your own repositories. On Enterprise Server it means any internal user with a single repo of their own. No special permissions, no admin role, no chained vulns. One git push from a stock client.

The post-exploit blast radius on GitHub.com would have been catastrophic. gitrpcd runs against shared storage nodes that host repository data for many tenants. Code execution as the git service user on one of those nodes meant read access to repository contents across the storage shard — not bounded by GitHub’s normal application-layer permission model. Wiz reports the impact as “read millions of repositories on the shared storage node, irrespective of the organization or user.” On Enterprise Server, where the entire instance is one tenant, the equivalent is full read access to every repo on the appliance plus the ability to pivot from the git node into the rest of the GHES infrastructure.

Impact Assessment

GitHub.com customers are not directly exposed at this point — that fix went out on March 4 and there’s no indication of in-the-wild exploitation prior to the patch. Wiz coordinated disclosure properly.

The acute risk is GitHub Enterprise Server. At public-disclosure time on April 28, 88% of Enterprise Server instances visible to scanners were on vulnerable versions. That means a large majority of self-hosted GHES appliances — many of which are run by exactly the kinds of organizations that self-host because they don’t trust their source code on a multi-tenant SaaS — were sitting on a one-git push RCE for at least 49 days after the patch was available. With the writeup now public and the exploit chain documented, weaponized PoCs are straightforward. Expect scanning and exploitation activity in the coming days.

If you run GHES, the threat model is simple: any user with credentials and any repository they can push to can compromise the appliance. That includes anyone who’s ever been issued a SAML-bound enterprise account, contractor access, or a stale machine user.

Mitigation

Patch immediately. Upgrade to one of the following or later in the same line:

  • 3.14.25
  • 3.15.20
  • 3.16.16
  • 3.17.13
  • 3.18.8
  • 3.19.4
  • 3.20.0

GHES upgrades within a major line are generally low-risk; cross-line upgrades require the standard sequence. If you’re more than one major line behind, plan the chained upgrade now — the gap from “patch shipped March 10” to “still unpatched April 28+” already represents an unacceptable window.

No effective compensating control exists if you can’t patch. Push options are part of the documented git protocol; you cannot meaningfully filter them at a proxy without breaking legitimate use. Disabling push entirely is the only reliable mitigation, and it’s not a real option for an SCM.

For detection:

  • Look for X-Stat header anomalies in any logging of internal babeld → gitrpcd traffic, particularly values containing semicolons inside push option fields. (Most operators won’t have this telemetry; vendors typically don’t log internal header content.)
  • Audit pre-receive hook activity on storage nodes. An unexpected hook execution path — anything outside the normal repository-scoped hook directories — is a strong indicator.
  • Review git push logs for unusual -o / --push-option values, especially anything containing =, ;, rails_env, custom_hooks_dir, or pre_receive_hooks substrings.
  • Audit account activity for the period between March 10 and your patch date: any push from an account that subsequently logged unusual filesystem or process activity on a backend node warrants investigation.

For GitHub.com customers, there is no action required from a vulnerability standpoint — the bug was patched server-side on March 4. If you want belt-and-suspenders assurance, Wiz’s writeup confirms no evidence of in-the-wild exploitation prior to the fix, and GitHub has not indicated any data exposure.

Why This One Matters

Most “critical” vulnerabilities in 2026 have been in third-party software that organizations choose to deploy. CVE-2026-3854 is in the substrate that the entire industry pushes code to. A successful exploitation of GitHub.com — had this been found by an attacker first — would have given read access to a meaningful slice of the world’s proprietary source code and CI/CD secrets, with downstream supply chain consequences that would have made the Trivy cascade look small.

The lesson for GHES operators is the same one that lands every quarter: self-hosting your SCM doesn’t isolate you from a supply chain incident, it just shifts the patch responsibility onto you. The 88% number is what happens when that responsibility isn’t met.