One git push to Own GitHub: The X-Stat Header Injection Behind CVE-2026-3854
TL;DR: A single git push -o command was enough to achieve arbitrary code execution on GitHub Enterprise Server — and, at time of disclosure, on shared storage nodes backing GitHub.com. The root cause: unsanitized user-controlled push options were embedded verbatim into GitHub's internal X-Stat header, a semicolon-delimited metadata bus shared by every component in the git push pipeline. With no sanitization and last-write-wins parsing semantics, any authenticated attacker could inject arbitrary security-critical fields, override sandbox protections, and land a shell. Wiz Research discovered this using AI-augmented binary reverse engineering — one of the first critical vulnerabilities found in closed-source production infrastructure by AI. 88% of GitHub Enterprise Server instances remained unpatched at time of public disclosure. If your GHES is below 3.19.3, you are almost certainly compromised or soon will be.
Background: The World's Most Trusted Code Vault
GitHub hosts over 500 million repositories. For enterprises running GitHub Enterprise Server (GHES), the self-hosted variant, it is not just a development convenience — it is the canonical source of truth for their codebase, CI/CD secrets, deployment keys, internal tooling, and compliance artifacts. Compromising a GHES instance is, for most organizations, equivalent to compromising the entire engineering function.
The git push pipeline processes billions of events per day. It is a multi-service architecture written in multiple languages, where compiled binaries pass security-critical metadata between components over an internal header protocol. The implicit trust between those services — the assumption that by the time data reaches an internal service it has been sanitized — is where CVE-2026-3854 lives.
Wiz Research identified the flaw in February 2026, submitted it March 4, and received one of GitHub's largest bug bounty payouts on record. GitHub.com was mitigated within six hours. GitHub Enterprise Server patches landed shortly after. What nobody could control was the patching cadence of the 88% of self-hosted instances that hadn't upgraded by the time Wiz published its full technical writeup.
Technical Analysis
1. The git push Pipeline Architecture
When a user runs git push over SSH, the request flows through four sequential components:
babeld — The entry point and git proxy. Receives the SSH connection, handles protocol negotiation, and forwards authentication checks to gitauth. After authentication, babeld constructs the X-Stat header that will be passed to all downstream services.
gitauth — An internal authentication and authorization service. Verifies credentials, checks push permissions, and returns session security policies: file size limits, branch naming constraints, LFS rules, and more. It does not handle execution.
gitrpcd — An internal RPC server. Receives the request from babeld, parses the X-Stat header, and sets up the execution environment for downstream git processes. Critically, gitrpcd performs no independent authentication — it trusts babeld completely and treats every field in X-Stat as authoritative.
Pre-receive hooks — Compiled Go binaries that enforce policy before a push is accepted: file size, branch rules, LFS integrity, admin-defined custom hooks.
The X-Stat header is the shared state carrier for this entire pipeline. It encodes key-value pairs using semicolons as field delimiters. Internal services parse it by splitting on ; and populating a map. The critical implementation detail: last-write-wins. If a key appears twice in the header, the second occurrence silently overwrites the first.
2. The Injection Point: Push Options
Git push options (git push -o key=value) are a standard protocol feature designed to pass hints to server-side hooks — things like "skip-ci" or "merge-request.create". They are arbitrary user-supplied strings.
When babeld encodes push options into the X-Stat header, it formats them as numbered fields: push_option_0=<value>, push_option_1=<value>, alongside a push_option_count field. The encoding was straightforward — value went in verbatim. No character filtering. No escaping of the ; delimiter.
This is the vulnerability in a single sentence: user-controlled push option values could contain semicolons, which are the X-Stat field delimiter, allowing an attacker to inject arbitrary additional fields into the header.
3. The Exploitation Chain
Consider the following crafted push option:
git push -o "legitimate_value;env=attacker_controlled_env;push_option_count=0" origin main
When babeld embeds this verbatim into X-Stat, the resulting header parses as three separate fields:
1. push_option_0 = legitimate_value
2. env = attacker_controlled_env ← injected
3. push_option_count = 0 ← injected, overrides legitimate count
Because gitrpcd trusts X-Stat completely and uses last-write-wins, the attacker's injected env field overrides the legitimate execution environment. The downstream pre-receive hook binary then runs in the attacker-specified environment.
From there, the path to code execution is direct: override LD_PRELOAD, manipulate PATH to intercept subprocess calls, or use environment-based code execution gadgets in the hook binaries. Wiz's full exploit bypassed sandboxing entirely and achieved arbitrary command execution on the server processing the push.
On GitHub.com, this meant RCE on shared storage nodes — nodes where Wiz confirmed access to millions of public and private repositories belonging to other users and organizations. The blast radius on GHES is worse: full server compromise, all repositories, all internal secrets, all admin credentials.
4. AI-Augmented Discovery
This vulnerability is also a landmark for a different reason: it was discovered primarily through AI-assisted reverse engineering.
The components involved — babeld, gitrpcd, gitauth — are closed-source compiled binaries. Historically, auditing them required laborious manual reverse engineering, limiting the practical attack surface researchers could cover. Wiz used IDA MCP (a Model Context Protocol integration with IDA Pro) to automate binary analysis at scale: reconstructing internal protocols, mapping data flow between services, and systematically identifying locations where user input influenced internal service behavior across the entire pipeline.
This is not the first use of AI in vulnerability research, but it is among the most consequential. The same technique is now available to nation-state threat actors and well-funded criminal groups. The implication: the audit surface of closed-source production infrastructure — previously protected partly by the sheer cost of manual RE — is now significantly more exposed.
5. Patch Analysis
GitHub fixed the issue by sanitizing push option values before embedding them in X-Stat: semicolons are now stripped or escaped before inclusion. Additionally, field-level validation was added in gitrpcd to reject fields injected through option values.
The patch touches babeld's push option encoding path and adds header integrity validation on the receiving end. This is a defense-in-depth fix — both preventing injection at the source and rejecting malformed headers downstream.
Fixed versions:
| GHES Version Series | Fixed Release |
|---|---|
| 3.14.x | 3.14.24 |
| 3.15.x | 3.15.19 |
| 3.16.x | 3.16.15 |
| 3.17.x | 3.17.12 |
| 3.18.x | 3.18.6 |
| 3.19.x | 3.19.3 |
GitHub.com: fully mitigated server-side, no user action required.
Indicators of Compromise
There is no network signature for this vulnerability — exploitation is indistinguishable from a normal git push at the transport layer. Detection must come from host-side telemetry on GHES instances.
Shell / process indicators:
- Unexpected child processes spawned by
git-receive-packor pre-receive hook binaries with unusual parent chains - Processes with modified
LD_PRELOADorPATHenvironment variables initiated from the git push service account - Hook binaries executing
curl,wget,bash -c,python, orncwith external network destinations - Execution of commands not in the standard hook binary call graph
File system indicators:
- New files written to hook binary directories (
/data/user/repos/.../hooks/) by non-admin processes - Unexpected shared libraries dropped into hook execution paths
- Modification of hook wrapper scripts outside of standard admin operations
Log indicators (GHES):
X-Statheader values containing semicolons inbabeldaccess logs (these should now be sanitized; presence suggests an unpatched or bypassed instance)- Unusually long
push_optionfield values in access logs - Pre-receive hook exit codes outside expected range alongside anomalous execution times
Network indicators (post-compromise):
- GHES instance initiating outbound connections to non-GitHub, non-CDN, non-update endpoints
- Data exfiltration patterns: large outbound transfers from GHES storage nodes
Lyrie Take
Three things about CVE-2026-3854 are strategically significant beyond the vulnerability itself.
First, the supply chain multiplier. GitHub Enterprise Server is not just a product — it is the upstream of everything. Compromise a GHES instance and you inherit the ability to inject into every downstream CI/CD pipeline, every artifact repository, every deployment key. The blast radius is not the GHES server; it is every system that trusts code coming out of it. This is the same threat model as the SolarWinds and XZ Utils attacks, but with a single authenticated git push as the entry point.
Second, AI finds what humans couldn't afford to look for. Wiz found this in closed-source binaries using AI-assisted RE at a cost and speed that was previously uneconomical. This is a one-way door. Nation-state actors and ransomware crews with ML capabilities will apply the same technique to other critical infrastructure components that have historically been protected by the sheer labor cost of analysis. The audit surface of the internet just expanded significantly.
Third, 88% unpatched is not a number — it is a hunting list. Two days after Wiz published the full exploitation chain, 88% of GHES instances had not upgraded. Every attacker with a Shodan subscription and a git client now has a target directory. The window between "patch released" and "mass exploitation" has collapsed to hours. If you are running GHES and have not upgraded, assume compromise pending forensic confirmation.
Lyrie's autonomous detection layer monitors for post-exploitation behaviors at machine speed — unusual subprocess chains, environment variable anomalies, and lateral movement patterns — without relying on signatures that didn't exist until Wiz published today. Human-speed IR is not adequate here.
Defender Playbook
Immediate (next 4 hours)
1. Verify GHES version: curl -s https://<your-ghes-host>/api/v3/meta | jq .installed_version — if below the fixed release for your series, treat as compromised and patch first.
2. Emergency patch: Upgrade to the minimum fixed version for your series (see table above). GitHub's upgrade documentation: https://docs.github.com/en/enterprise-server@latest/admin/upgrading-your-instance
3. Review recent push option usage: Pull babeld access logs for the past 30 days. Look for push_option values containing semicolons or unusually long option strings:
grep push_option /var/log/github/babeld.log | grep ";" | sort | uniq -c | sort -rn | head -50
4. Check hook directories for unexpected files:
find /data/user/repos -name "*.so" -newer /etc/github/enterprise.lic 2>/dev/null
find /data/user/repos -path "*/hooks/*" -newer /etc/github/enterprise.lic 2>/dev/null
5. Review outbound network connections from GHES host: Look for unexpected destinations in firewall logs for the past 30 days.
Short-Term (next 7 days)
6. Audit admin and service account SSH keys: Assume keys on a compromised GHES instance are burned. Rotate all deployment keys and PATs that were used against an unpatched instance.
7. Review recent CI/CD pipeline outputs: Look for unexpected steps, new dependencies, or modified artifact hashes in builds processed by pipelines with push-triggered hooks.
8. Enable audit log streaming (if not already): Ship GHES audit logs to a SIEM outside the GHES host. An attacker with RCE can modify local logs.
9. Restrict push option usage at the babeld/admin policy level while the patch is staged: Not all environments use push options; if your hooks don't consume them, consider disabling push options in GHES admin settings temporarily.
Detection Tuning
10. Add process execution alerting for git-receive-pack and pre-receive hook processes spawning shells, network utilities, or interpreters. This is low-noise in a standard GHES deployment and high-signal for this attack class.
11. Alert on new shared library files written to hook execution paths. No legitimate GHES operation writes .so files into repository hook directories.
Sources
1. Wiz Research — "Securing GitHub: Wiz Research uncovers Remote Code Execution in GitHub.com and GitHub Enterprise Server (CVE-2026-3854)" — https://www.wiz.io/blog/github-rce-vulnerability-cve-2026-3854
2. GitHub Security Blog — "Securing the git push pipeline: responding to a critical remote code execution vulnerability" — https://github.blog/security/securing-the-git-push-pipeline-responding-to-a-critical-remote-code-execution-vulnerability/
3. The Cyber Express — "CVE-2026-3854 RCE Flaw In GitHub Enterprise Server" — https://thecyberexpress.com/cve-2026-3854-rce-github-enterprise-server/
4. NVD — CVE-2026-3854 — https://nvd.nist.gov/vuln/detail/CVE-2026-3854
5. GitHub Advisory — GHSA for CVE-2026-3854 — https://github.com/advisories/GHSA-cve-2026-3854
Lyrie.ai Cyber Research Division — Senior Analyst Desk
Lyrie Verdict
Lyrie's autonomous defense layer flags this class of exposure the moment it surfaces — no signature update required.