Introduction
A critical security vulnerability has been disclosed in GitHub.com and GitHub Enterprise Server that poses a severe risk to organizations relying on GitHub for source code management and DevOps pipelines. Tracked as CVE-2026-3854 with a CVSS score of 8.7 (High), this command injection flaw enables an authenticated attacker with repository push access to achieve unauthenticated remote code execution (RCE) through nothing more than a single git push command.
The severity of this vulnerability cannot be overstated. In modern software supply chains, GitHub serves as the central hub for code collaboration, CI/CD orchestration, and deployment automation. An attacker exploiting this flaw could move laterally from a compromised repository to the underlying hosting infrastructure, inject malicious code into build pipelines, or exfiltrate intellectual property and secrets stored in the environment.
Defenders must act immediately to assess exposure, apply patches, and implement detection mechanisms to identify potential exploitation attempts.
Technical Analysis
Affected Products and Versions
- GitHub Enterprise Server (all versions prior to 3.14.5)
- GitHub.com (cloud infrastructure — patched at server level, no customer action required for SaaS users)
Vulnerability Details
| Attribute | Value |
|---|---|
| CVE Identifier | CVE-2026-3854 |
| CVSS v3.1 Score | 8.7 (High) |
| Attack Vector | Network (Adjacent) |
| Attack Complexity | Low |
| Privileges Required | Low (push access to repository) |
| User Interaction | None |
| Scope | Changed |
| Impact | Confidentiality, Integrity, Availability |
How the Vulnerability Works
CVE-2026-3854 is a classic command injection vulnerability in the Git server-side processing component of GitHub Enterprise Server. The flaw exists in how the git-receive-pack handler processes specially crafted references (refs) during a push operation.
Attack Chain:
-
Initial Access: Attacker obtains or already has legitimate push access to a repository (either through compromised credentials, social engineering, or by contributing to a public project)
-
Exploitation: Attacker executes a maliciously crafted
git pushcommand containing shell metacharacters in branch or tag names: bash
git push origin HEAD:refs/heads/$(whoami)
-
Command Injection: The GitHub server-side Git processor fails to properly sanitize the ref name before passing it to a shell command, allowing arbitrary command execution in the context of the Git service account
-
Privilege Escalation: The Git service account on GitHub Enterprise Server has elevated permissions, enabling the attacker to:
- Access all repository data
- Extract SSH keys and access tokens
- Modify CI/CD pipeline configurations
- Pivot to other services running on the host
-
Impact: Full compromise of the GitHub Enterprise Server instance and potential lateral movement to connected systems
Exploitation Status
As of the disclosure date:
- Proof-of-Concept (PoC): Publicly available
- In-the-Wild Exploitation: Not yet confirmed, but high probability of active scanning
- CISA KEV: Not yet added, but expected given severity
Detection & Response
SIGMA Rules
---
title: GitHub Enterprise - Suspicious Git Push with Command Injection Characters
id: a1b2c3d4-5678-490a-bcde-123456789012
status: experimental
description: Detects git push operations containing shell metacharacters in ref names, indicative of CVE-2026-3854 exploitation attempts
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-3854
- https://github.blog/security/security-advisories/
author: Security Arsenal
date: 2026/04/06
tags:
- attack.execution
- attack.t1059.004
- cve-2026-3854
logsource:
category: process_creation
product: linux
detection:
selection:
ParentImage|endswith: '/git'
Image|endswith: '/git-receive-pack'
CommandLine|contains:
- 'refs/heads/$('
- 'refs/heads/`'
- 'refs/heads/;'
- 'refs/heads/|'
- 'refs/heads/&&'
- 'refs/tags/$('
- 'refs/tags/`'
condition: selection
falsepositives:
- Legitimate branch names with special characters (rare)
- Misconfigured git hooks
level: high
---
title: GitHub Enterprise - Unexpected Shell Spawned from Git Process
id: b2c3d4e5-6789-490b-cdef-234567890123
status: experimental
description: Detects shell processes spawned from git-receive-pack, potentially indicating successful command injection exploitation
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-3854
author: Security Arsenal
date: 2026/04/06
tags:
- attack.execution
- attack.t1059
- attack.initial_access
- cve-2026-3854
logsource:
category: process_creation
product: linux
detection:
selection:
ParentImage|endswith: '/git-receive-pack'
Image|endswith:
- '/bash'
- '/sh'
- '/zsh'
condition: selection
falsepositives:
- Legitimate git hooks using shell scripts
level: critical
---
title: GitHub Enterprise - Suspicious Network Activity from Git Service Account
id: c3d4e5f6-7890-490c-def0-345678901234
status: experimental
description: Detects outbound network connections from the git service account to non-GitHub endpoints, possible post-exploitation C2
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-3854
author: Security Arsenal
date: 2026/04/06
tags:
- attack.command_and_control
- attack.t1071
- attack.exfiltration
- cve-2026-3854
logsource:
category: network_connection
product: linux
detection:
selection:
User|contains:
- 'git'
- 'github'
DestinationPort|not:
- 22
- 443
- 80
- 9418
condition: selection
falsepositives:
- Legitimate git operations to custom internal servers
- Git over SSH to non-standard ports
level: medium
KQL (Microsoft Sentinel / Defender)
-- Detect git push operations with shell metacharacters in ref names
let SuspiciousChars = dynamic([\"$(\", \"`\", \";\", \"|\", \"&&\", \"||\"]);
Syslog
| where Facility == \"auth\" or Facility == \"authpriv\" or Facility == \"daemon\"
| where ProcessName contains \"git\"
| where SyslogMessage has \"receive-pack\"
| extend ParsedMessage = extract_all(@\"refs/(heads|tags)/([^\s]+)\", dynamic[\"type\", \"refname\"], SyslogMessage)
| mv-expand ParsedMessage
| extend RefType = ParsedMessage[0], RefName = ParsedMessage[1]
| where RefName has_any(SuspiciousChars)
| project TimeGenerated, HostName, ProcessName, SyslogMessage, RefType, RefName, Severity
| order by TimeGenerated desc
-- Detect shell processes spawned from git-receive-pack
DeviceProcessEvents
| where InitiatingProcessFileName =~ \"git-receive-pack\"
| where FileName in~ (\"bash\", \"sh\", \"zsh\", \"ksh\")
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName, FileName,
CommandLine, InitiatingProcessCommandLine, ProcessId, InitiatingProcessId
| order by Timestamp desc
-- Detect outbound connections from git service account to suspicious endpoints
DeviceNetworkEvents
| where InitiatingProcessAccountName contains \"git\"
| where RemotePort !in (22, 443, 80, 9418)
| where RemoteIPType == \"Public\"
| project Timestamp, DeviceName, InitiatingProcessAccountName,
RemoteUrl, RemoteIP, RemotePort, InitiatingProcessFileName
| order by Timestamp desc
Velociraptor VQL
-- Hunt for suspicious git processes with command injection indicators
SELECT Pid, Ppid, Name, Exe, CommandLine, Username, Ctime
FROM pslist()
WHERE Name =~ 'git'
AND CommandLine =~ 'receive-pack'
AND (CommandLine =~ '\\$\\('
OR CommandLine =~ '`'
OR CommandLine =~ ';'
OR CommandLine =~ '\\|\\|'
OR CommandLine =~ '&&'
OR CommandLine =~ '\\|')
-- Identify shell processes spawned from git parent processes
SELECT child.Pid, child.Ppid, child.Name, child.Exe, child.CommandLine,
parent.Name AS ParentName, parent.CommandLine AS ParentCommandLine,
child.Username
FROM pslist() AS child
JOIN pslist() AS parent ON child.Ppid = parent.Pid
WHERE parent.Name =~ 'git'
AND parent.Name =~ 'receive-pack'
AND child.Name IN ('bash', 'sh', 'zsh', 'ksh', 'dash')
-- Scan for git configuration files with suspicious modifications
SELECT FullPath, Mtime, Size, Mode, OSPath.Basename
FROM glob(globs=\"/**/.git/config\")
WHERE Mtime > now() - 7d
AND OSPath.Basename = \"config\"
ORDER BY Mtime DESC
-- Check git hook files for unexpected changes
SELECT FullPath, Mtime, Size, Mode
FROM glob(globs=\"/**/.git/hooks/*\")
WHERE Mtime > now() - 7d
AND Mode != \"755\"
AND Mode != \"644\"
ORDER BY Mtime DESC
Remediation Script (Bash)
#!/bin/bash
# GitHub Enterprise Server - CVE-2026-3854 Remediation Script
# Version: 1.0
# Purpose: Detect vulnerable GitHub Enterprise Server versions and apply patches
set -e
RED='\\033[0;31m'
GREEN='\\033[0;32m'
YELLOW='\\033[1;33m'
NC='\\033[0m' # No Color
# Minimum safe version
SAFE_VERSION=\"3.14.5\"
log() {
echo -e \"${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1\"
}
warn() {
echo -e \"${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING:${NC} $1\"
}
error() {
echo -e \"${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR:${NC} $1\"
}
check_root() {
if [[ $EUID -ne 0 ]]; then
error \"This script must be run as root\"
exit 1
fi
}
detect_ghe_version() {
log \"Detecting GitHub Enterprise Server version...\"
if [ -f /etc/github/release ]; then
CURRENT_VERSION=$(cat /etc/github/release | grep \"version\" | cut -d'=' -f2 | tr -d '\"')
log \"Current GitHub Enterprise Server version: $CURRENT_VERSION\"
echo \"$CURRENT_VERSION\"
else
error \"Could not detect GitHub Enterprise Server version\"
exit 1
fi
}
compare_versions() {
if [[ \"$1\" == \"$2\" ]]; then
echo \"0\"
elif [[ \"$1\" = $(echo -e \"$1\
$2\" | sort -V | head -n1) ]]; then
echo \"-1\" # $1 < $2
else
echo \"1\" # $1 > $2
fi
}
check_vulnerability() {
local current=$1
local safe=$2
log \"Checking if version $current is vulnerable to CVE-2026-3854...\"
if [ $(compare_versions \"$current\" \"$safe\") -lt 0 ]; then
warn \"VULNERABLE: Current version $current is below patched version $safe\"
return 1
else
log \"SECURE: Current version $current is patched\"
return 0
fi
}
apply_patch() {
log \"Applying GitHub Enterprise Server security patch...\"
# Check if ghe-update utility exists
if ! command -v ghe-update &> /dev/null; then
error \"ghe-update not found. Please ensure this is a GitHub Enterprise Server\"
exit 1
fi
# Check for internet connectivity to download patches
if ! ping -c 1 -W 2 github.com &> /dev/null; then
warn \"No internet connectivity detected. Please download patch manually and run:\"
warn \" ghe-upgrade <patch-file>\"
return 1
fi
# Run the upgrade command
log \"Downloading and applying latest security patch...\"
ghe-upgrade latest || {
error \"Failed to apply patch automatically\"
error \"Please manually download the patch from: https://enterprise.github.com/releases\"
error \"Then run: ghe-upgrade <patch-file>\"
exit 1
}
log \"Patch applied successfully. A reboot is required.\"
return 0
}
implement_mitigation() {
log \"Implementing temporary mitigations...\"
# Restrict git push operations to trusted users only
log \"Creating temporary denylist for untrusted users...\"
# Backup existing configuration
cp /data/user/common/ssh/authorized_keys /data/user/common/ssh/authorized_keys.bak.$(date +%Y%m%d_%H%M%S) 2>/dev/null || true
# Add logging for all git operations
log \"Enabling enhanced git operation logging...\"
echo \"$(date) - CVE-2026-3854 mitigation applied - Enhanced logging enabled\" >> /var/log/github/git-mitigation.log
# Note to admin
warn \"Temporary mitigations are NOT a substitute for patching\"
warn \"Please apply the official patch as soon as possible\"
}
scan_for_exploitation() {
log \"Scanning for potential exploitation indicators...\"
local found_indicators=0
# Check git logs for suspicious ref patterns
if grep -r \"refs/.*/[\\$\\`\\;\\|]\" /data/repositories/*/refs 2>/dev/null; then
warn \"Found suspicious ref names in repository data\"
found_indicators=1
fi
# Check for unexpected processes
if ps aux | grep -E \"git-receive-pack.*(bash|sh|zsh)\" | grep -v grep; then
warn \"Found shell processes spawned from git-receive-pack\"
found_indicators=1
fi
# Check auth logs for suspicious push activities
if grep -E \"git.*push.*(\\$|\\`|;|\\|)\" /var/log/auth.log 2>/dev/null; then
warn \"Found suspicious git push operations in auth logs\"
found_indicators=1
fi
if [ $found_indicators -eq 0 ]; then
log \"No immediate indicators of exploitation found\"
else
error \"Potential exploitation indicators detected. Please investigate immediately.\"
error \"Preserve logs and consider engaging incident response.\"
return 1
fi
}
main() {
log \"Starting GitHub Enterprise Server CVE-2026-3854 Remediation\"
log \"=\"
check_root
scan_for_exploitation
CURRENT_VERSION=$(detect_ghe_version)
if check_vulnerability \"$CURRENT_VERSION\" \"$SAFE_VERSION\"; then
log \"System is already patched against CVE-2026-3854\"
exit 0
fi
echo \"\"
warn \"Your system is VULNERABLE to CVE-2026-3854\"
warn \"Critical severity: Remote Code Execution via git push\"
echo \"\"
read -p \"Do you want to apply the security patch now? (y/n): \" -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
if apply_patch; then
implement_mitigation
log \"=\"
log \"Remediation completed successfully\"
log \"Please reboot the system to complete the patch installation\"
log \"After reboot, run: ghe-version to verify the update\"
fi
else
implement_mitigation
warn \"Mitigations applied but system remains vulnerable\"
warn \"Please apply the patch as soon as possible\"
fi
log \"=\"
log \"For official documentation, visit: https://docs.github.com/en/enterprise-server@latest/admin/overview\"
}
main \"$@\"
Remediation
Immediate Action Required
-
Patch GitHub Enterprise Server to version 3.14.5 or later immediately
- Patches are available from the GitHub Enterprise Server release portal
- Download URL: https://enterprise.github.com/releases
- Upgrade command:
ghe-upgrade <patch-package>.pkg
-
Reboot Required: After patch application, a full system reboot is mandatory
-
Post-Patch Verification: Run
ghe-versionto confirm the successful update
Vendor Advisory References
- GitHub Security Advisory: https://github.com/security/advisories
- GitHub Enterprise Documentation: https://docs.github.com/en/enterprise-server@latest/admin/release-notes
- CVE Record: https://nvd.nist.gov/vuln/detail/CVE-2026-3854
Temporary Workarounds (If Patching Delayed)
If immediate patching is not feasible due to maintenance windows, implement the following mitigations:
-
Restrict Push Access: Immediately revoke push access from all users except essential maintainers bash ghe-org-permission-set --org
--repo --permission read --user -
Audit All SSH Keys: Review and rotate all SSH and API tokens with repository write access bash ghe-admin-ssh-check
-
Enable Branch Protection Rules: Enforce strict branch protection requiring pull request reviews bash ghe-api graphql '{query: "mutation($input:CreateBranchProtectionRuleInput!){createBranchProtectionRule(input:$input){branchProtectionRule{id}}}", variables: {input:{repositoryId:"
",pattern:"main",requiresApprovingReviews:true,requiresStrictStatusChecks:true}}}' -
Review Git Logs: Audit recent git push operations for anomalous ref names bash
find /data/repositories -name \"refs\" -exec sh -c 'grep -rE \"\\$|\\`|;|\\|\" {}' \\;
CISA/Regulatory Deadlines
As this is a high-severity vulnerability with known exploit code:
- CISA KEV Inclusion: Expected within 48 hours of public disclosure
- Mandatory Patch Deadline: 7 days from KEV listing for Federal Civilian Executive Branch (FCEB) agencies
- Recommended Industry Timeline: Patch within 48-72 hours
Post-Incident Actions
If exploitation is suspected or confirmed:
- Isolate the GitHub Enterprise Server from the network
- Preserve forensic evidence: Memory dump, disk image, logs
- Rotate all credentials: SSH keys, API tokens, deploy keys
- Audit all repositories for unauthorized commits
- Review CI/CD pipeline logs for injected artifacts
- Notify affected stakeholders and consider public disclosure requirements
Related Resources
Security Arsenal Managed SOC Services AlertMonitor Platform Book a SOC Assessment soc-mdr Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.