Brief Summary: CVE-2026-6951 — simple-git RCE via --config Flag Bypass

A short review of CVE-2026-6951, a critical RCE in the simple-git npm package caused by an incomplete fix for CVE-2022-25912. Includes patch analysis and affected version details.

CVE Analysis

7 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-04-24

Brief Summary: CVE-2026-6951 — simple-git RCE via --config Flag Bypass
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

An incomplete security fix in the simple-git npm package has re-opened a critical remote code execution path that was supposed to have been closed in 2022. CVE-2026-6951, carrying a CVSS 3.1 score of 9.8, allows attackers to bypass argument filtering and execute arbitrary commands on the host system by simply switching from the short form -c flag to the long form --config flag when injecting git configuration overrides.

simple-git is a widely used Node.js library that provides a lightweight programmatic interface for running git commands. With over 8.7 million weekly downloads and 7,789 dependent packages on npm, it occupies a central position in the JavaScript ecosystem's build and deployment tooling. A vulnerability at this layer has outsized supply chain implications.

Technical Information

The root cause of CVE-2026-6951 lies in how simple-git parses and filters arguments before passing them to the underlying git binary. In 2022, CVE-2022-25912 was disclosed because attackers could use the -c flag to override git configuration at runtime, specifically enabling protocol.ext.allow=always to activate the ext:: remote helper protocol. The ext:: protocol is a git feature that executes arbitrary shell commands as part of a remote URL, making it a well known code execution vector when combined with configuration injection.

The mitigation for CVE-2022-25912 added a blocklist that intercepted the short -c option. However, it failed to account for the functionally equivalent long form --config flag. Because git treats -c key=value and --config key=value identically, an attacker could simply switch to --config to sail right past the filter.

Attack Flow

The exploitation path is straightforward:

  1. The attacker identifies a Node.js application that uses simple-git and passes user controlled input into the options or customArgs parameters of a git operation such as clone.
  2. The attacker supplies --config and protocol.ext.allow=always as options. The blocklist does not intercept these because it only checks for -c.
  3. The attacker provides a malicious clone URL using the ext:: protocol, embedding an arbitrary shell command within the URL.
  4. simple-git passes these arguments unmodified to the git binary, which honors the config override, enables the ext:: protocol, and executes the embedded command with the privileges of the Node.js process.

This pattern of bypasses is not isolated. A related vulnerability, CVE-2026-28292, demonstrated a similar bypass where attackers used uppercase characters (PROTOCOL.ALLOW=always) to evade case sensitive regex checks in the blockUnsafeOperationsPlugin. Together, these bypasses illustrate the fundamental fragility of regex based argument filtering as a security boundary.

Patch Information

The fix for CVE-2026-6951 is implemented in commit 89a2294, authored by Steve King on April 11, 2026, and shipped in simple-git version 3.36.0 (released April 12, 2026). The commit is titled "Environment Parsing (#1156)" and touches 29 files with over 1,000 lines of additions, representing a substantial rework of how the library detects and blocks dangerous arguments.

The patch goes considerably further than simply adding --config to the blocklist. Here are the key architectural changes:

Expanded Config Key Blocklist

The old detect-config-writes.ts only blocked six config keys: protocol.allow, core.sshCommand, core.fsmonitor, core.gitProxy, core.hooksPath, and diff.external. The replacement file, detect-vulnerable-config-writes.ts, introduces a much broader blocklist with a new helper called preventExpandedConfigBuilder that uses regex expansion so patterns like credential.helper also match scoped variants (e.g., credential.https://example.com.helper). The new blocklist now covers:

  • alias.* (arbitrary command aliases)
  • core.askPass, core.editor, core.pager (binary substitution vectors)
  • credential.helper (credential interception)
  • diff.textconv, diff.command, filter.clean, filter.smudge (file content interception)
  • gpg.program, gpg.ssh.program, gpg.x509.program (signing binary substitution)
  • init.templateDir (hook planting via templates)
  • merge.driver, mergetool.cmd, mergetool.path (merge time code execution)
  • remote.*.receivepack, remote.*.uploadpack (per remote pack binary overrides)
  • sequence.editor (rebase time binary substitution)

Expanded Flag Detection

The old detect-upload-pack.ts only flagged --upload-pack, --receive-pack, and related options. The new detect-vulnerable-flags.ts adds --template to the flag blocklist, preventing template directory injection via the command line as well as via config.

New Environment Variable Scanning

This is entirely new functionality. The commit introduces parseEnv(), which inspects the environment variables being passed to the git child process. It maps security sensitive environment variable names (like GIT_ASKPASS, GIT_SSH_COMMAND, GIT_CONFIG_COUNT, GIT_EXTERNAL_DIFF, GIT_TEMPLATE_DIR, GIT_PROXY_COMMAND, EDITOR, PAGER, etc.) to their corresponding vulnerability categories. When GIT_CONFIG_COUNT is set, the parser reads the corresponding GIT_CONFIG_KEY_n / GIT_CONFIG_VALUE_n pairs and subjects those injected keys to the same blocklist checks as inline -c values.

Unified Vulnerability Check Entry Point

A new vulnerabilityCheck(tokens, env) function combines both argument parsing and environment scanning into one call. The block-unsafe-operations-plugin.ts was updated so its action handler now receives the task's environment context and passes it into this unified check:

// Before (only checked args): action(args) { const parsed = parseArgv(...args); for (const vulnerability of parsed.vulnerabilities.vulnerabilities) { ... } } // After (checks args AND environment): action(args, { env }) { for (const vulnerability of vulnerabilityCheck(args, env)) { ... } }

This ensures that even if an attacker circumvents argument level protections by injecting config through environment variables (for example, setting GIT_CONFIG_COUNT=1 plus GIT_CONFIG_KEY_0=protocol.ext.allow and GIT_CONFIG_VALUE_0=always), the library will detect and block the attempt.

Granular Opt In Model

Each new blocked category introduces a corresponding opt in flag (e.g., allowUnsafeAlias, allowUnsafeCredentialHelper, allowUnsafeTemplateDir, etc.) in the unsafe configuration object, giving developers explicit control if they genuinely need to use these features with trusted input. The VulnerabilityCategoryFlags interface was expanded from 7 categories in the previous version to over 20.

To remediate, upgrade to simple-git version 3.36.0 or later:

npm install simple-git@latest

When upgrading, ensure transient dependencies are fully updated. Maintainers reported that partial upgrades leaving @simple-git/argv-parser mismatched caused breaking TypeError issues in CI environments.

Affected Systems and Versions

All versions of the simple-git npm package prior to version 3.36.0 are affected. The vulnerability is exploitable in any Node.js application where untrusted user input can reach the options or customArgs parameters of simple-git functions such as clone.

Version 3.36.0, released on April 12, 2026, contains the fix.

Vendor Security History

The simple-git project has experienced a recurring pattern of security bypasses stemming from its reliance on blocklist based argument filtering:

  • CVE-2022-25912: The original RCE via -c flag injection enabling the ext:: protocol. This was the vulnerability that CVE-2026-6951 bypasses.
  • CVE-2026-28292: A bypass using uppercase characters (PROTOCOL.ALLOW=always) to evade case sensitive regex checks in the blockUnsafeOperationsPlugin.
  • CVE-2026-6951: The current vulnerability, bypassing the -c blocklist via the equivalent --config flag.

To the maintainer's credit, each fix has been progressively more comprehensive. The patch for CVE-2026-6951 represents a significant architectural improvement, moving from narrow blocklist entries to a defense in depth approach that covers config keys, command line flags, and environment variables simultaneously.

References

Detect & fix
what others miss

Security magnifying glass visualization