CVE-2026-3854 exposed a critical trust-boundary failure in the GitHub Enterprise Server (GHES) push pipeline. A value supplied through a standard Git push option could be copied into internal, semicolon-delimited metadata and later interpreted as trusted configuration. For organizations that use GHES to host private source code, deployment credentials, and connections to internal development systems, the issue shows why metadata crossing from a client-controlled protocol into privileged server-side processing must be treated as untrusted at every stage.
Vulnerability overview
CVE-2026-3854 is a high-severity remote code execution vulnerability in GitHub’s server-side git push pipeline. An authenticated user with push access to a repository could craft a push option that introduced additional fields into GitHub’s internal request metadata.
Downstream services interpreted those fields as server-generated configuration. By overriding values that governed hook processing, an attacker could move pre-receive hook execution outside the expected sandbox and run commands as the git service user. Repository-level write access could therefore become server-side code execution. The vulnerability received a CVSS 4.0 score of 8.7 (High).
The central security issue was not the presence of a shell metacharacter in a command. It was a data-format mismatch: Git allowed a delimiter that GHES reused to separate trusted internal fields. The analysis below follows that value across the trust boundary, explains how duplicate fields changed security-sensitive configuration, and shows how the resulting primitive reached the hook-execution path.
From push option to trusted metadata
The relevant data flow
A client sends push options alongside commit data using -o or –push-option. In the SSH path, babeld accepts the connection, gitauth evaluates identity and repository permissions, and the authorized request is represented in a semicolon-delimited internal header named X-Stat. The request then reaches gitrpcd, which parses that metadata and prepares the pre-receive-hook environment. The security boundary lies where a client-controlled push option is embedded in the same structure as server-generated authorization and execution settings.
Figure: SSH git push data flow. The vulnerable boundary appeared when babeld placed user-controlled push options inside trusted X-Stat metadata.
This is the trust boundary that matters. gitrpcd and the hook logic treated every X-Stat field as if babeld had created it. CVE-2026-3854 allowed part of that supposedly trusted metadata to come directly from the user.
Delimiter confusion created a field-injection primitive
Git rejects NUL and line-feed characters in push-option values but permits semicolons. GHES also used semicolons to separate key=value pairs inside X-Stat. Because the push option was embedded without neutralizing that delimiter, a semicolon could end the intended value and begin a new metadata field.
A semicolon supplied by the user could therefore terminate the intended push-option value and begin a new metadata field. The following harmless example uses a fictional field name rather than working exploit syntax:
processing_mode=production;push_option_0=normal_value;processing_mode=modified_value
When the parser encountered the same field more than once, the final value took precedence. The combination of delimiter confusion and last-write-wins parsing therefore allowed client input to override a value set earlier by the server.
This was an internal metadata-injection primitive rather than direct command injection. Its significance depended on which fields could be replaced and whether those fields influenced a later execution boundary.
How the injected fields reached hook execution
Three X-Stat fields formed the execution chain: rails_env, custom_hooks_dir, and repo_pre_receive_hooks.
rails_env selected the hook-execution path. Replacing its expected production value shifted processing to a non-production path in which hooks ran directly rather than inside the normal sandbox. custom_hooks_dir set the base directory for hook lookup, while repo_pre_receive_hooks influenced the resolved hook path. Together, the overrides changed the execution mode and redirected path resolution beyond the expected directory.
The pre-receive stage could then launch a program already present on the server outside the expected sandbox as the git service user. Exploitation required authenticated push access, but not administrator privileges, malicious commit content, or victim interaction.
Impact
GitHub Enterprise Server
Successful exploitation allowed an attacker to execute commands as the git service user rather than as root. Even without root privileges, this account could reach repository data, configuration files, and secrets used by GHES. In practice, someone with permission to push to one repository could move beyond that repository and compromise the wider server.
GitHub.com
Wiz’s published research reported that the same underlying issue affected GitHub.com and created cross-tenant risk because code execution occurred on shared repository infrastructure. GitHub’s incident response stated that the researchers accessed repository records for validation but did not access other users’ repository contents.
Affected and fixed versions
GitHub’s incident post identifies the following minimum patched builds:
- GHES 3.14.25 or later
- GHES 3.15.20 or later
- GHES 3.16.16 or later
- GHES 3.17.13 or later
- GHES 3.18.7 or later
- GHES 3.19.4 or later
- GHES 3.20.0 or later
Mitigation and detection
Upgrading closes the vulnerability. GHES administrators should also check for signs that it was exploited before the update was installed. GitHub recommends reviewing /var/log/github-audit.log for push operations containing ; in their push options.
Any matches should be reviewed alongside the account, repository, source address, and time of the push. Administrators should also look for unusual process execution, file access, or repository activity around the same time.
If a push appears suspicious, preserve the relevant logs and system state before making changes that could erase evidence. Rotate potentially exposed credentials and internal secrets, follow the organization’s incident-response process.
Conclusion
CVE-2026-3854 demonstrates how a protocol feature can become dangerous when its data is copied into a privileged internal format without a clear encoding boundary. A semicolon that was valid in a Git push option became a field separator in X-Stat; duplicate-key handling then allowed client input to replace trusted configuration that influenced hook execution.
The immediate priority for GHES administrators is to upgrade to a fixed release and review historical push activity. The broader engineering lesson is to keep user-controlled values separate from security-sensitive state: encode delimiters before serialization, reject duplicate keys, and validate execution-related fields again at the hook boundary.
References
- GitHub — Securing the Git push pipeline: Responding to a critical remote code execution vulnerability
- Wiz Research — GitHub RCE vulnerability: CVE-2026-3854 technical breakdown
Authors:
Supreet Kaur
Vinay Kumar
Adrip Mukherjee


