CVE-2026-3854 Breakdown: How a Single Git Push Almost Hijacked GitHub

2026.04.29 12 min
CVE-2026-3854 Breakdown: How a Single Git Push Almost Hijacked GitHub

CVE-2026-3854 Breakdown: How a Single Git Push Almost Hijacked GitHub

Quick summary

  • CVE-2026-3854 carried a CVSS score of 8.7 — an authenticated git push could trigger remote code execution on GitHub's backend.
  • Wiz Research disclosed the flaw on 4 March 2026 — GitHub validated it and patched github.com within 75 minutes.
  • 88% of GitHub Enterprise Server instances remained vulnerable at public disclosure on 28 April 2026.
  • No customer data was accessed — GitHub's forensic investigation confirmed zero exploitation in the wild.

On 28 April 2026, GitHub disclosed CVE-2026-3854: a critical command-injection bug in its internal git pipeline that let any authenticated user run arbitrary code on GitHub's backend with a single git push command. Wiz Research found it. GitHub fixed it on github.com in 75 minutes. The CVSS score landed at 8.7, and the impact statement is the part that should make every security team uncomfortable — code execution on a shared storage node meant cross-tenant access to millions of public and private repositories belonging to other organisations.

This wasn't a supply-chain attack. It wasn't an unpatched dependency. It was a delimiter-handling mistake in a closed-source internal binary that nobody outside GitHub had ever seen — and the researchers found it anyway.

What CVE-2026-3854 actually is

CVE-2026-3854 is an X-Stat field injection vulnerability in babeld, GitHub's internal git proxy, that allowed authenticated push-access users to inject crafted fields into internal service headers and ultimately execute arbitrary commands as the git service user. Wiz Research disclosed it through GitHub's bug bounty programme on 4 March 2026.

The mechanics are textbook injection, just buried five layers deep in proprietary infrastructure. When a developer runs git push -o key=value, GitHub's babeld proxy embeds those user-supplied option values into an internal header called X-Stat and forwards them to downstream services like gitauth and gitrpcd. The X-Stat header uses semicolons as field delimiters. Babeld did not sanitise semicolons in the user-supplied values.

The result: a semicolon in a push option wasn't metadata — it was a new field injected into a trusted internal header. Downstream services parsed the header with last-write-wins semantics and dutifully treated the attacker's injected fields as authoritative truth.

The exploitation chain — three injections, one git push

GitHub's defence-in-depth architecture meant a single injection wasn't enough. Wiz's exploit chain required three sequential injections, all piggy-backing on one push command.

1. Sandbox bypass via rails_env

The git service runs custom hook execution inside a production sandbox that strips dangerous environment variables. By injecting a non-production rails_env value into the X-Stat header, the attacker convinced the downstream service it was running in a development context — disabling the sandbox entirely.

2. Hook directory hijack via custom_hooks_dir

With the sandbox out of the way, the second injection pointed custom_hooks_dir at an attacker-controlled location. This told the pre-receive hook handler where to look for hook scripts, breaking out of the legitimate hook directory.

3. Path-traversal RCE via repo_pre_receive_hooks

The final injection added a crafted entry to repo_pre_receive_hooks containing path-traversal sequences (../../../) that resolved to arbitrary binaries on the filesystem. When the push triggered the pre-receive phase, those binaries executed as the git service user.

End-to-end: one git push to a repository the attacker had push rights on, three injected fields, full RCE on GitHub's backend. The Hacker News headline — "Critical GitHub RCE Flaw Exploitable via Single Git Push" — wasn't hyperbole.

Why this was worse than "yet another RCE"

GitHub's multi-tenant architecture means a single backend node hosts repositories from many independent organisations. Code execution on one of those nodes gave the attacker read access to the underlying shared storage — and therefore to the source code of every other tenant on that node, regardless of whether they had any relationship to the attacker.

In Wiz's words: "effectively allowing an attacker to read millions of repositories on the shared storage node, irrespective of the organization or user." That includes private repositories. That includes proprietary code. That includes secrets committed to git history.

The blast radius wasn't the attacker's victim repository — it was the platform.

Timeline: 75 minutes from report to patch

GitHub's response is the bright spot in this story. The full timeline, per the company's official write-up:

Time (UTC)Event
4 March 2026, 17:45Wiz Research submits report via GitHub Bug Bounty
4 March 2026, 17:45–18:25Internal validation (40 minutes)
4 March 2026, 19:00Fix deployed to github.com (75 minutes total)
10 March 2026CVE-2026-3854 assigned; GHES patches released
28 April 2026Public disclosure

GitHub also confirmed two forensic results that matter: "No other users or accounts triggered this code path" and "No customer data was accessed, modified, or exfiltrated." That wouldn't have been true if a less responsible researcher had found it first.

The GitHub Enterprise Server problem

Github.com was patched within 75 minutes. GitHub Enterprise Server (GHES) was not — and at the time of disclosure, 88% of GHES instances remained vulnerable, according to Wiz Threat Center telemetry.

GHES is self-hosted. Patching is the customer's responsibility, and large enterprises have change windows, regression-test cycles, and compliance approvals that don't move at github.com speed. The patched releases are:

  • 3.14.25 or later
  • 3.15.20 or later
  • 3.16.16 or later
  • 3.17.13 or later
  • 3.18.7 or later
  • 3.19.4 or later
  • 3.20.0 or later

If you run GHES on any version below the appropriate line, an authenticated user with push rights to any repository on the instance can take it over. That is the practical exposure today.

How Wiz found it: AI-augmented reverse engineering

The discovery method matters. babeld, gitauth, and gitrpcd are closed-source binaries — there is no public repository to grep, no commit history to bisect. Wiz Research used AI-augmented reverse engineering tools (IDA MCP) to analyse the compiled binaries, reconstruct GitHub's internal protocol, and trace user input through the multi-service architecture.

Wiz described the work as "one of the first critical vulnerabilities discovered in closed-source binaries using AI." That tracks with a broader trend covered in our analysis of AI-discovered zero-days: the bar for finding deep, protocol-level bugs in opaque infrastructure has dropped, and it has dropped for both defenders and attackers. The same techniques are now within reach of any sufficiently motivated adversary.

The team behind the discovery — Sagi Tzadik, Nir Ohfeld, Ronen Shustin, Hillai Ben-Sasson, Yuval Avrahami, and Noam Malron — earned what GitHub CISO Alexis Wales called "one of the highest rewards available in our Bug Bounty program."

What GHES administrators should do this week

1. Patch immediately

Upgrade to one of the patched GHES versions listed above. There is no workaround — sanitisation lives inside the patched binaries. If your change-management process requires a justification, the justification is this: any user with push access to any repository on your instance can become root-equivalent on the host.

2. Search audit logs for indicators of compromise

Check /var/log/github-audit.log for push operations whose push_options field contains semicolons. GitHub's investigation found no exploitation in the wild, but that result applies to github.com — your self-hosted instance has its own forensic surface area. Specific indicators to look for:

  • X-Stat header values containing semicolons in stored proxy logs
  • Non-production rails_env values appearing in push-related logs
  • custom_hooks_dir references pointing outside the configured hooks path
  • Path-traversal sequences (../) in repo_pre_receive_hooks entries
  • Unexpected child processes spawned by the pre-receive hook handler

3. Audit who has push access to what

The minimum exploitation precondition was push access to some repository on the instance. Many organisations grant push access more liberally than they grant repository-creation access. Pull current permissions and confirm that "anyone with a corporate SSO seat" is not the same set as "anyone allowed to push code."

4. Make sure you have a disclosure channel of your own

The 75-minute fix on github.com was only possible because Wiz had somewhere to send the report. Organisations without a published Vulnerability Disclosure Programme routinely lose weeks between researcher contact and triage — and under NIS2, a coordinated vulnerability disclosure process is no longer optional for in-scope entities. The single biggest predictor of fast remediation is a published security.txt and a triage process behind it.

5. Add GHES version drift to your continuous external monitoring

Self-hosted infrastructure rots silently. 88% of GHES instances were unpatched at disclosure because nobody was watching the version numbers. Continuous external scanning catches version drift before the next CVSS-8.7 disclosure forces a fire drill — the same pattern seen with MongoBleed exploitation, where unpatched, internet-facing infrastructure was the entire attack surface.

Key Takeaways

  • CVE-2026-3854 was a CVSS 8.7 RCE in GitHub's internal git proxy — exploitable by any authenticated user with push access via a single git push command.
  • GitHub fixed github.com in 75 minutes after Wiz Research's bug bounty submission, and forensics confirmed zero exploitation in the wild.
  • 88% of GitHub Enterprise Server instances were still vulnerable at public disclosure — patching to GHES 3.19.4 (or the appropriate maintenance stream) is urgent, not optional.
  • The exploit required three sequential injections — a sandbox bypass, a hook directory hijack, and a path-traversal RCE — all riding on one unsanitised semicolon.
  • AI-augmented reverse engineering changes the discovery economics — critical bugs in closed-source infrastructure are now findable in days, not years, by both researchers and adversaries.

FAQ

What is CVE-2026-3854?

CVE-2026-3854 is a CVSS 8.7 command-injection vulnerability in GitHub's internal git push pipeline, disclosed on 28 April 2026. It allowed authenticated users to execute arbitrary code on GitHub's backend by injecting unsanitised semicolons into git push option values.

Was github.com exploited?

No. GitHub's forensic investigation confirmed that no other users triggered the vulnerable code path and that no customer data was accessed, modified, or exfiltrated. The vulnerability was reported by Wiz Research and patched on github.com within 75 minutes.

Which GitHub Enterprise Server versions are affected?

All GHES versions up to and including 3.19.1 are vulnerable. Patched releases are 3.14.25, 3.15.20, 3.16.16, 3.17.13, 3.18.7, 3.19.4, and 3.20.0 or later.

How was CVE-2026-3854 discovered?

Wiz Research used AI-augmented reverse engineering (IDA MCP) to analyse GitHub's closed-source binaries and reconstruct the internal git protocol. The team — Sagi Tzadik, Nir Ohfeld, Ronen Shustin, Hillai Ben-Sasson, Yuval Avrahami, and Noam Malron — submitted the finding through GitHub's Bug Bounty programme.

What should GHES administrators do now?

Upgrade to a patched GHES version, search /var/log/github-audit.log for push options containing semicolons, audit push-access permissions across all repositories, and add GHES version drift to continuous external monitoring. There is no workaround short of patching.


The 88% of GHES instances still vulnerable at disclosure had one thing in common: nobody was watching their version numbers from the outside. Continuous external scanning catches version drift before the next CVSS-8.7 forces a fire drill. See how RavenEye AI vulnerability scanning surfaces unpatched infrastructure.