Automated Threat Modeling

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, with 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 reopened a critical remote code execution path that was supposed to have been closed in 2022. CVE-2026-6951, with a CVSS 3.1 score of 9.8, lets an attacker bypass argument filtering and execute arbitrary commands on the host system. All it takes is 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. It has over 8.7 million weekly downloads and 7,789 dependent packages on npm, and it sits at the center of a lot of the JavaScript ecosystem's build and deployment tooling. A vulnerability at this layer reaches far down the supply chain.

Technical Information

CVE-2026-6951 comes from 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, so combined with configuration injection it is a well-known code execution vector.

The mitigation for CVE-2022-25912 added a blocklist that intercepted the short -c option. It did not account for the long-form --config flag, which does exactly the same thing. Because git treats -c key=value and --config key=value identically, an attacker could switch to --config and 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 is not the only bypass of its kind. A related vulnerability, CVE-2026-28292, used uppercase characters (PROTOCOL.ALLOW=always) to evade case-sensitive regex checks in the blockUnsafeOperationsPlugin. Between them, the two bypasses show how fragile regex-based argument filtering is 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. It is a substantial rework of how the library detects and blocks dangerous arguments.

The patch does considerably more than add --config to the blocklist. The main architectural changes follow.

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. A new helper called preventExpandedConfigBuilder uses regex expansion so that patterns like credential.helper also match scoped variants (e.g., credential.https://example.com.helper). The new blocklist 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, which blocks template directory injection from the command line as well as through config.

New Environment Variable Scanning

This part is entirely new. The commit introduces parseEnv(), which inspects the environment variables 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 vulnerability categories. When GIT_CONFIG_COUNT is set, the parser reads the matching GIT_CONFIG_KEY_n / GIT_CONFIG_VALUE_n pairs and runs those injected keys through the same blocklist checks as inline -c values.

Unified Vulnerability Check Entry Point

A new vulnerabilityCheck(tokens, env) function combines argument parsing and environment scanning in one call. The block-unsafe-operations-plugin.ts 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)) { ... } }

So if an attacker gets around the 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 still detect and block the attempt.

Granular Opt-In Model

Each new blocked category has a matching opt-in flag (e.g., allowUnsafeAlias, allowUnsafeCredentialHelper, allowUnsafeTemplateDir, etc.) in the unsafe configuration object. Developers who genuinely need one of these features with trusted input have explicit control over turning it back on. The VulnerabilityCategoryFlags interface grew 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 you upgrade, make sure transient dependencies are fully updated too. Maintainers reported that partial upgrades, which left @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 had repeated security bypasses, all stemming from its reliance on blocklist-based argument filtering:

  • CVE-2022-25912: The original RCE via -c flag injection enabling the ext:: protocol. This is 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 more comprehensive than the last. The patch for CVE-2026-6951 is a significant architectural improvement. It replaces narrow blocklist entries with a defense-in-depth approach that covers config keys, command-line flags, and environment variables at the same time.

References

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Gerrit
  • CVS
  • Jira
  • Linear
  • Slack
  • Security Compass
Explore integrations
Security magnifying glass visualization