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:
- The attacker identifies a Node.js application that uses
simple-gitand passes user controlled input into theoptionsorcustomArgsparameters of a git operation such asclone. - The attacker supplies
--configandprotocol.ext.allow=alwaysas options. The blocklist does not intercept these because it only checks for-c. - The attacker provides a malicious clone URL using the
ext::protocol, embedding an arbitrary shell command within the URL. simple-gitpasses these arguments unmodified to thegitbinary, which honors the config override, enables theext::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
-cflag injection enabling theext::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 theblockUnsafeOperationsPlugin. - CVE-2026-6951: The current vulnerability, bypassing the
-cblocklist via the equivalent--configflag.
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
- NVD: CVE-2026-6951
- CVE Record: CVE-2026-6951
- Snyk: Remote Code Execution (RCE) in simple-git
- GitHub Gist: RCE in simple-git by KKC73
- Fix Commit: Environment Parsing (#1156)
- Patch File for Commit 89a2294
- simple-git Releases
- Snyk: CVE-2022-25912 (Original RCE)
- GitHub Advisory: CVE-2026-28292
- Pull Request #1156: Environment Parsing
- simple-git on npm
- steveukx/git-js on GitHub



