LIVE NEWSROOM · --:-- · May 23, 2026
A LIBRARY FOR SECURITY RESEARCHERS

CVE-2026-3854: How the GitHub Enterprise Server RCE Works and How to Verify You’re Patched

Post on X LinkedIn

CVE-2026-3854 is a critical remote code execution vulnerability (CVSS 8.7) in GitHub’s internal git infrastructure affecting both GitHub.com and all GitHub Enterprise Server (GHES) releases prior to the fixed versions. An authenticated attacker with push access to any repository — including one they created themselves — can execute arbitrary commands on the underlying server with a single git push. GitHub.com was patched within 75 minutes of internal validation on March 4, 2026; at the time of public disclosure on April 28, 88% of self-hosted GHES instances remained unpatched.

// 01 Background: The babeld Proxy and Push Options

GitHub’s git infrastructure routes push operations through an internal proxy service called babeld. When a user runs git push, babeld collects metadata — repository path, user identity, push options — and forwards it to backend services via a custom HTTP header: X-Stat.

X-Stat uses a semicolon-delimited key=value format:

X-Stat: repo_path=/path/to/repo;user_id=12345;push_option=ci-skip

Git push options (specified with -o) are a standard git feature that lets clients pass arbitrary strings to server-side hooks. They are widely used for CI skip flags, deployment signals, and hook configuration. The problem: babeld copies push option values into X-Stat verbatim, without stripping or escaping semicolons.

// 02 How the Injection Works

Because X-Stat uses semicolons as field delimiters, a semicolon embedded in a push option value terminates the current field and begins a new one. Backend services parse X-Stat with last-write-wins semantics: when a key appears more than once, the later value silently overrides the earlier one.

An attacker can inject security-critical internal fields by crafting a push option containing a semicolon:

git push -o 'ci-skip;rails_env=development;custom_hooks_dir=/tmp/evil' origin main

Babeld constructs:

X-Stat: ...;push_option=ci-skip;rails_env=development;custom_hooks_dir=/tmp/evil

The downstream service sees rails_env and custom_hooks_dir as trusted internal fields — indistinguishable from values babeld set legitimately — and acts on them.

// 03 Exploitation Chain: Three Fields to Shell

Wiz Research, who discovered and reported the vulnerability, documented a three-stage chain:

Stage 1 — Disable the sandbox. The rails_env field controls whether hook execution runs in a production sandbox or a more permissive development code path. Injecting rails_env=development drops sandbox restrictions.

Stage 2 — Redirect hook lookups. The custom_hooks_dir field sets the base directory from which pre-receive hook scripts are loaded. Pointing it to an attacker-controlled writable path — such as a directory inside a freshly-cloned repository — allows arbitrary hook content to be staged.

Stage 3 — Execute arbitrary code. The repo_pre_receive_hooks field accepts a JSON structure specifying hook binary paths. Combined with path traversal sequences, this resolves to any binary accessible on the filesystem. That binary executes as the git service user when the push is processed.

# Illustrative payload — demonstrates the injection structure
git push \
  -o 'ci-skip;rails_env=development;custom_hooks_dir=/tmp/;repo_pre_receive_hooks=[{"path":"../../usr/bin/id"}]' \
  origin main

The attack requires nothing beyond a standard git client and push access to one repository. No elevated privileges, no prior foothold, no social engineering.

// 04 Impact: Cross-Tenant Exposure at Scale

On GitHub.com’s shared storage infrastructure, the git service user has filesystem read/write access across the storage node handling the push. Wiz confirmed that successful exploitation would expose repositories from multiple unrelated organizations co-hosted on the same node — potentially millions of repositories per compromised storage node.

For GitHub Enterprise Server, the impact is total instance compromise: all hosted repository data, secrets in environment variables, internal service credentials, and GitHub Actions runner registration tokens.

Timeline:
March 4, 2026, 17:45 UTC — Wiz submits report to GitHub Security
March 4, 2026, 19:00 UTC — Fix deployed to GitHub.com (75-minute turnaround)
April 28, 2026 — Coordinated public disclosure; 88% of GHES instances still unpatched at time of disclosure

// 05 Patch Verification Checklist for GHES Admins

GitHub.com is already patched and requires no action. If you run GitHub Enterprise Server, work through this checklist now.

Step 1 — Confirm your GHES version

# SSH into your GHES appliance
ghe-version

Alternatively: Management Console → https://\<hostname>:8443 → Settings → About GitHub Enterprise.

Fixed minimum versions by branch:

BranchMinimum safe version
3.143.14.25
3.153.15.20
3.163.16.16
3.173.17.13
3.183.18.7
3.193.19.4
3.203.20.0

Any version below the minimum for its branch is vulnerable. Treat an internet-accessible unpatched instance as potentially compromised until upgraded and logs are reviewed.

Step 2 — Scan audit logs for exploit indicators

Semicolons in push option values are the fingerprint of this attack. Search your audit log:

sudo grep -E '"push_option".*"[^"]*;[^"]*"' /var/log/github-audit.log

If your audit log is JSON-formatted, use a targeted query:

sudo python3 -c "
import sys, json
for line in sys.stdin:
    try:
        entry = json.loads(line)
        if ';' in entry.get('push_option', ''):
            print(line.strip())
    except Exception:
        pass
" < /var/log/github-audit.log

Any result warrants manual review. Also check for unusual pre-receive hook execution spikes around the same timestamps:

sudo grep 'pre_receive' /var/log/github/gitauth.log | \
  awk -F'T' '{print $1}' | sort | uniq -c | sort -rn | head -20

Step 3 — Rotate instance secrets if exposure is suspected

If your GHES instance was internet-accessible and unpatched for any period after January 2026, rotate:

  • GitHub App private keys
  • OAuth application client secrets
  • Webhook secrets
  • SSH host keys (the git user has filesystem access to /etc/ssh on some GHES configurations)
  • Credentials stored in environment variables visible to the git service user
  • GitHub Actions self-hosted runner registration tokens

Step 4 — Add defence-in-depth: reject semicolons in push options

After upgrading, add a server-side pre-receive hook to reject push options containing semicolons at the application layer. This provides a residual defence against similar injection vectors:

#!/bin/bash
# /data/user/repos/custom-hooks/pre-receive
while read oldrev newrev refname; do
  for i in $(seq 0 $((GIT_PUSH_OPTION_COUNT - 1))); do
    opt=$(eval echo "\$GIT_PUSH_OPTION_$i")
    if [[ "$opt" == *';'* ]]; then
      echo "Error: push option contains invalid character (semicolon)." >&2
      exit 1
    fi
  done
done

// 06 If You Cannot Patch Immediately

Three mitigations reduce exposure while an upgrade window is scheduled:

  1. Restrict push access — Users with read-only repository access cannot trigger the exploit. Audit push permissions and remove unnecessary grants. This is the most effective short-term control.
  2. Block external git push at the network layer — Restrict TCP 22 and HTTPS/git to known CIDR ranges if your GHES does not require internet-facing push access.
  3. Strip push option headers at your reverse proxy — Remove Git-Push-Option-Count and all Git-Push-Option-N headers at the load balancer. This disables push-option-dependent CI workflows but eliminates the injection surface entirely.

// 07 Conclusion

CVE-2026-3854 is a textbook trust boundary violation: user-supplied data entered a structured internal protocol without sanitization, and last-write-wins header semantics turned it into a privilege escalation primitive. GitHub’s 75-minute turnaround on GitHub.com is a strong incident response benchmark. The 88% unpatched rate on GHES at disclosure is a reminder that self-hosted deployments carry the full weight of their own patch cycles.

If you manage GitHub Enterprise Server, version verification and audit log review are the immediate actions — not next sprint.

See our analysis of the GlassWorm VS Code supply chain attack for another case study in how developer tooling becomes an attack surface →

    TE
    Team Ciphers Security

    The Ciphers Security editorial team — practitioners covering daily threat intel, CVE deep-dives, and hands-on cybersecurity research. About us →

    Previous GlassWorm VS Code Extensions: How to Audit Your Dev Environment for Malicious Extensions Next CISA Adds Actively Exploited ConnectWise and Windows Flaws to KEV

    Latest News

    Megalodon: Supply Chain Attack Backdoors 5,561 GitHub Repos in Six Hours via CI/CD Workflow Injection Megalodon supply chain attack compromised 5,561 GitHub repos in 6 hours on May 18, injecting malicious CI/CD workfl… Stolen Gemini API Keys and AI Fraud: How 'Quantum Patriot' Drained Crypto Wallets via Fake QAnon Content A Russian-speaking fraudster used 73 stolen Gemini API keys and an automated Python pipeline to generate fake QAnon… Stack String Obfuscation in C: The Technique That Blinds AV, YARA, and Static Scanners Stack strings let malware hide C2 URLs and API names from static analysis. Learn how the technique works in C, whic… YARA-X 1.16.0: Faster Scans, Panic Fixes, and Neovim LSP Support YARA-X 1.16.0 ships with performance improvements across 10 PRs, constant folding for bitwise ops, configurable mat… Instructure Removed from ShinyHunters' Leak Site as Canvas Breach Deadline Passes Instructure was quietly removed from ShinyHunters' extortion site after the May 12, 2026 deadline — no data dump, n… Costa Rica Joins Have I Been Pwned as the 42nd Government Costa Rica's CSIRT gains free access to Have I Been Pwned's government domain monitoring service, becoming the 42nd… LummaC2 Infostealer Targets US Critical Infrastructure: CISA-FBI Advisory AA25-141B and DOJ Domain Seizures CISA and FBI advisory AA25-141B details LummaC2 MaaS infostealer TTPs targeting critical infrastructure. DOJ seized… MacSync Stealer: Hackers Abuse Google Ads and Claude.ai Chats to Push Mac Malware Russian-speaking attackers combine Google Ads and Claude.ai shared chats in a ClickFix campaign deploying MacSync S…
    Scroll to Top
    Ad