simple-git (the Node.js git wrapper, 15.1M weekly downloads): four vendor advisories on 2026-09-26 — the default blockUnsafeOperationsPlugin missed git's `include.path`/`includeIf` config includes (CVE-2026-102826, 8.1), long-option abbreviations like `--receive-p` (CVE-2026-102827, 8.1), `trailer.<token>.cmd` (CVE-2026-102828, 9.2) and the `VISUAL` editor variable (CVE-2026-102829, 9.2) — each is OS command execution when an application lets untrusted data reach git's arguments, config or environment; fixed in 4.0.0 / 4.0.1 and @simple-git/argv-parser 2.0.1, and 4.0 now blocks ambient environment variables by default
TL;DR
simple-git is the library most Node.js code uses to run git — 15,136,117 downloads in the week ending 2026-10-04 — including a lot of the bots, CI helpers and coding agents that clone repositories or commit on a user's behalf. Its blockUnsafeOperationsPlugin is a denylist of git options and config keys that can execute commands (--upload-pack, core.sshCommand, protocol.allow, ext:: …), on by default since 3.15.0. On 2026-09-26 the maintainer published four advisories for things the denylist did not know about, and GitHub (as CNA) issued CVEs on 09-29; the database's reviewed npm critical listing surfaced them on 10-05:
| Gap in the denylist | Id | Score | Affected → fixed |
|---|---|---|---|
Git config includes. -c include.path=<file> loaded an arbitrary gitconfig, which can carry core.sshCommand; a pending fix's regex /\s*include.path/ also missed the conditional includeIf.gitdir:…path form |
GHSA-g4wm-2vf7-vfgr / CVE-2026-102826 | 8.1 (3.1, AC:H) | ≤ 3.36.0 → 4.0.0 |
Long-option abbreviation. Git accepts any unambiguous prefix, so --receive-p and --exe passed a filter matching --receive-pack and --exec; "a residual" of CVE-2026-28291 |
GHSA-858h-whjf-mvg5 / CVE-2026-102827 | 8.1 (3.1, AC:H) | ≤ 3.36.0 → 4.0.0 |
trailer.<token>.cmd. Documented by git as "a shell command invoked by git interpret-trailers"; not classified as unsafe config |
GHSA-x6jw-m9v5-85vh / CVE-2026-102828 | 9.2 (4.0, AT:P) | ≥ 3.15.0, < 4.0.1 → 4.0.1 |
VISUAL. The env parser classified EDITOR, GIT_EDITOR and GIT_SEQUENCE_EDITOR as unsafe but dropped VISUAL before classification, so a forwarded VISUAL=<binary> ran on commit --amend or rebase -i |
GHSA-v5rq-49vh-5v5c / CVE-2026-102829 | 9.2 (4.0, AT:P) | @simple-git/argv-parser < 2.0.1 → 2.0.1 |
The registry shows simple-git@4.0.0 published 2026-09-25 10:38 UTC, 4.0.1 at 11:03, 4.0.2 on 09-26, and @simple-git/argv-parser@2.0.1 on 09-26; latest is 4.0.2. The 4.0 release is a breaking major: abbreviated long options now throw GitConfigurationError, ambient environment variables are no longer passed to the git child process unless listed in a new allow-list, and the unsafe ones need a second opt-in. That is the right design — it closes the whole class the four advisories sample — and it means upgrading is a code change, not a version bump.
What happened
The precondition is the same in all four: the application passes something an attacker influenced into simple-git — customArgs, SimpleGitOptions.config, inline -c values, or the process environment — and relies on the plugin to stop the dangerous ones. The vendor's own impact statements are careful about this: CVE-2026-102828 says risk "is limited to applications passing untrusted data into simple-git configuration or command arguments," CVE-2026-102826's chain also needs attacker-writable file storage the process can read, and CVE-2026-102829 needs the application to forward untrusted environment values. Each CVSS vector carries AC:H or AT:P for that reason. Where the precondition holds, the result is a shell command running "with the operating-system identity and permissions of the Node.js process."
This is the third round. The denylist was already bypassed twice this year: CVE-2026-28291 (GHSA-jcxm-m3jx-f287, 8.1, < 3.32.0, 2026-04-12) found three-character option variants (--u, -4u, -lu …) that reached --upload-pack, itself an incomplete patch for CVE-2022-25860; CVE-2026-28292 (GHSA-r275-fr43-pm7q, 9.8, 3.15.0 – < 3.32.3, same day, CodeAnt AI) found the protocol.allow regex was case-sensitive while git lower-cases config keys, so PROTOCOL.ALLOW=always re-enabled ext::. September's four are the same shape — git has more spellings than the list — and the 4.0 redesign (block the environment by default, reject abbreviations outright) is the maintainer declining to keep playing it.
Why the agent angle. A coding agent that commits, pushes, clones a repository a user named, or applies a .gitconfig-shaped suggestion is exactly an application that passes model- or user-influenced strings to git. This repo's GitSpawn cluster is the same family one layer up: git config values that execute, reached through an agent. simple-git sits underneath many of those tools in Node; whether a given tool is exposed depends on which of its inputs reach git() arguments, which no advisory here enumerates and this sweep did not attempt to.
Am I affected?
npm ls simple-git @simple-git/argv-parser --all 2>/dev/null
grep -n '"simple-git"\|"@simple-git/argv-parser"' package-lock.json pnpm-lock.yaml yarn.lock 2>/dev/null | head
# Where do arguments, config or env reach git?
grep -rn "customArgs\|\.raw(\|\.env(\|config:\s*\[" --include='*.ts' --include='*.js' src/ 2>/dev/null | head -40
grep -rn "allowUnsafe\|unsafe:\s*{" --include='*.ts' --include='*.js' src/ 2>/dev/null
simple-git≤ 3.36.0 → CVE-2026-102826 and -102827; 3.15.0 through 4.0.0 → CVE-2026-102828;@simple-git/argv-parser< 2.0.1 (the transitive dependency4.0.0still pulled2.0.0) → CVE-2026-102829.- Any
unsafe: { … }allowance you set deliberately turns the corresponding guard off; the advisories describe default-configuration bypasses, so an explicit allowance is already a wider exposure. - Not affected if no untrusted value can reach arguments, config or the environment of the git child process — a CLI you run by hand on your own inputs qualifies; a web service, bot or agent generally does not.
If you are affected
- Upgrade to
simple-git@4.0.2(which brings@simple-git/argv-parser@2.0.1). Read the 4.0.0 release notes first: the default export andgitPare gone (import { simpleGit } from "simple-git"), abbreviated long options throw, and environment variables you relied on reaching git (GIT_SSH_COMMAND,GIT_CONFIG_*, proxies, credential helpers) must now be allow-listed — the vendor spells the optionallowEnvoronmentin the notes. - If you cannot take the major yet, stop passing untrusted strings into
customArgs,configand the environment — that removes the precondition for all six CVEs in this file's history, not just the four new ones. - Audit for exploitation where untrusted input did reach git: look for
-c include.path,includeIf,trailer.,--receive-p,--exe,protocol.allowor aVISUAL=assignment in request logs, job parameters or agent transcripts, and for unexpected child processes of your Node service — if-your-local-ai-agent-was-exploited.md covers the agent case, if-your-webapp-was-compromised.md the service case. - Treat credentials the Node process could read (deploy keys, tokens in env) as exposed if the audit is inconclusive — rotating-cloud-credentials.md.
Prevention
- A denylist in front of git is not a security boundary. Git accepts option prefixes, case-insensitive config keys, includes, trailers and a dozen
*.cmd/*Commandkeys; the fixes here went from patching the list to removing the inputs. Do the same in your own wrappers: fixed argument vectors, no-cfrom untrusted data, a minimal explicit environment — prevention/agent-sandboxing.md. - Run git-driving services and agents as a low-privilege user in a container with no credentials beyond the one repository they need, so the "privileges of the Node.js process" clause is worth little.
- Keep
simple-giton the current major and watch its advisory tab: six command-execution advisories in six months, each an incomplete fix of the last, is a dependency whose releases need reading — prevention/supply-chain-attack-surface.md.
Why this matters for vibe coders
The generated "GitHub bot" or "auto-commit agent" almost always imports simple-git, almost always builds a clone/commit call from a string the user or the model supplied, and almost always runs with the token that can push. The library's safety plugin was the thing standing between that string and a shell, and it has now been bypassed six ways this year. The 4.0 upgrade is worth the breaking change precisely because it stops depending on the list.
Sources
- GHSA-g4wm-2vf7-vfgr — simple-git allows command execution through unblocked Git configuration includes (CVE-2026-102826) — fetched 2026-10-06: 8.1
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H,≤ 3.36.0→ 4.0.0, Sink A (include.pathabsent from the denylist) and Sink B (the/\s*include.path/regex missingincludeIf), thecore.sshCommandchain and its attacker-writable-storage precondition, PR #1193, finders bhaswanthc and NotAFlightRisk, published 2026-09-26. - GHSA-858h-whjf-mvg5 — unsafe-operations plugin bypass via git long-option abbreviation (CVE-2026-102827) — fetched 2026-10-06: 8.1,
≤ 3.36.0→ 4.0.0,--receive-p/--exe, "a residual" of CVE-2026-28291, finder anir0y plus nine additional reporters, published 2026-09-26. - GHSA-x6jw-m9v5-85vh — unsafe-operation guard does not block trailer command configuration (CVE-2026-102828) — fetched 2026-10-06: 9.2
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H,≥ 3.15.0, < 4.0.1→ 4.0.1, the git documentation quote, the "limited to applications passing untrusted data" impact statement, reporter sec-reex, published 2026-09-26. - GHSA-v5rq-49vh-5v5c —
VISUALeditor environment variable omitted from unsafe editor detection (CVE-2026-102829) — fetched 2026-10-06: 9.2 (4.0),@simple-git/argv-parser < 2.0.1→ 2.0.1, theGitEnvKeysmapping inparse-env.ts,commit --amend/rebase -i, PR #1201, published 2026-09-26. - NVD API — CVE-2026-102826, CVE-2026-102828, CVE-2026-102829 — fetched 2026-10-06: all three published 2026-09-29 by
security-advisories@github.com, scores as above, references to the fix commits (98864c6, d762810c, 68874c23), PRs #1193 / #1198 / #1201 and the release tags. - steveukx/git-js — security advisories tab — fetched 2026-10-06: the four September entries plus the two April ones.
- GHSA-jcxm-m3jx-f287 — Command Execution via Option-Parsing Bypass in simple-git (CVE-2026-28291) — fetched 2026-10-06: 8.1,
< 3.32.0, the three-character option variants, incomplete fix of CVE-2022-25860, reporter JuHwiSang, published 2026-04-12. - GHSA-r275-fr43-pm7q — blockUnsafeOperationsPlugin bypass via case-insensitive protocol.allow (CVE-2026-28292) — fetched 2026-10-06: 9.8,
≥ 3.15.0, < 3.32.3→ 3.32.3, the missing/iflag,PROTOCOL.ALLOW=always→ext::, reporter CodeAnt-AI-Security, published 2026-04-12. - steveukx/git-js — release simple-git@4.0.0 — fetched 2026-10-06: the breaking changes (default export removed, abbreviated long options throw
GitConfigurationError, ambient environment blocked by default with anallowEnvoronmentallow-list, dual opt-in for unsafe variables,allowUnsafeExecdetection forrebase -x/--exec). - npm registry —
simple-gitand@simple-git/argv-parsertime,dist-tags— queried 2026-10-06: 3.32.3 2026-02-26, 3.36.0 2026-04-12, 4.0.0 2026-09-25 10:38 UTC, 4.0.1 11:03 UTC, 4.0.2 2026-09-26; argv-parser 2.0.0 2026-09-25, 2.0.1 2026-09-26;latest4.0.2. - npm downloads API —
simple-git(week ending 2026-10-04) — 15,136,117. - GitHub Advisory Database — reviewed
npmcritical listing — fetched 2026-10-06: CVE-2026-102828 and -102829 listed Oct 5 (database date). - Related in this repo: GitSpawn git-config agent RCE cluster, GuardFall shell-injection guard bypasses.