Every CVE Search/ Get API key

CVE-2026-102826

simple-git allows command execution through unblocked Git configuration includes

8.1 HighPublic exploitFix available

simple-git, an interface for running git commands in any node.js application, enables applications to execute Git operations from JavaScript. Prior to 4.0.0, the default blockUnsafeOperationsPlugin does not completely reject configuration includes supplied through customArgs to git.clone(). The missing include.path classification permits Git to load an attacker-controlled configuration file, and the initial remediation does not cover includeIf.<condition>.path, allowing the same file-loading primitive through a conditional include. A loaded configuration can set an executable Git option such as core.sshCommand, which Git invokes during the clone operation with the privileges of the Node.js process. Exploitation requires the application to pass attacker-influenced custom arguments and requires an attacker-controlled file that the process can read. This issue is fixed in 4.0.0.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
High
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

Exploit likelihood

0.46%Unchanged since Sep 30, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.1

simple-git allows command execution through unblocked Git configuration includes

simple-git, an interface for running git commands in any node.js application, enables applications to execute Git operations from JavaScript. Prior to 4.0.0, the default blockUnsafeOperationsPlugin does not completely reject configuration includes supplied through customArgs to git.clone(). The missing include.path classification permits Git to load an attacker-controlled configuration file, and the initial remediation does not cover includeIf.<condition>.path, allowing the same file-loading primitive through a conditional include. A loaded configuration can set an executable Git option such as core.sshCommand, which Git invokes during the clone operation with the privileges of the Node.js process. Exploitation requires the application to pass attacker-influenced custom arguments and requires an attacker-controlled file that the process can read. This issue is fixed in 4.0.0.

Record
CVE-2026-102826
CVSS 3.1
8.1 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-77, CWE-78
Updated
2026-11-02
EUVDEUVD-2026-89332 8.1

simple-git, an interface for running git commands in any node.js application, enables applications to execute Git operations from JavaScript. Prior to 4.0.0, the default blockUnsafeOperationsPlugin does not completely reject configuration includes supplied through customArgs to git.clone(). The missing include.path classification permits Git to load an attacker-controlled configuration file, and the initial remediation does not cover includeIf.<condition>.path, allowing the same file-loading primitive through a conditional include. A loaded configuration can set an executable Git option such as core.sshCommand, which Git invokes during the clone operation with the privileges of the Node.js process. Exploitation requires the application to pass attacker-influenced custom arguments and requires an attacker-controlled file that the process can read. This issue is fixed in 4.0.0.

Record
EUVD-2026-89332
CVSS 3.1
8.1 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-g4wm-2vf7-vfgr 8.1

simple-git allows command execution through unblocked Git configuration includes

Summary

An OS command injection vulnerability in git.clone() allows any application that flows attacker-influenced data into customArgs to execute arbitrary code. simple-git 3.36.0 (current latest on npm) ships without any include.path entry in the blockUnsafeOperationsPlugin denylist. Passing -c include.path=<file> via customArgs loads any local file as a gitconfig. The loaded file can set core.sshCommand (or any otherwise-denied key), and the next remote operation in the same clone executes the attacker's command.

PR #1167 (merged to main 2026-05-10, not yet released to npm) adds preventConfigBuilder('include.path', 'allowUnsafeInclude') to the denylist. The generated regex /\s*include.path/ closes the plain spelling but does not match the conditional form includeIf.<cond>.path. The variant therefore survives the upcoming release if the regex is not tightened in the same cycle.

This sits in the same denylist class as the prior incomplete-fix chain (CVE-2022-24433, CVE-2022-24066, CVE-2022-25912, CVE-2022-25860, CVE-2026-28291, CVE-2026-28292). include and includeIf are not referenced in any published advisory, in any commit prior to PR #1167, or anywhere in the 3.36.0 source.

Details

Two sinks share the same root cause: the denylist is incomplete.

Sink A: published 3.36.0 has no include.path entry

packages/argv-parser/src/vulnerabilities/detect-vulnerable-config-writes.ts in the v3.36.0 tag contains no entry for include.path or includeIf.*.path. The argv parser recognises -c include.path=<file> and -c includeIf.<cond>.path=<file> as config writes, but detectVulnerableConfigWrites iterates a denylist that does not include either key. The plugin returns no vulnerability and the operation proceeds.

Sink B: pending PR #1167 regex misses includeIf

PR #1167 adds:

const preventUnsafeConfig = [
   // ...
   preventConfigBuilder('include.path', 'allowUnsafeInclude'),
   // ...
];

preventConfigBuilder constructs a non-anchored regex from the string:

function preventConfigBuilder(config, category, message) {
   const regex = typeof config === 'string'
      ? new RegExp(`\\s*${config.toLowerCase()}`)
      : config;
   return function preventCommand(key) {
      if (regex.test(key)) { /* throw */ }
   };
}

For 'include.path', the generated regex is /\s*include.path/. The . between include and path is a regex wildcard. The engine matches include plus exactly one arbitrary character plus path. Conditional include keys have the form includeIf.<condition>.path (includeIf.gitdir:.path, includeIf.onbranch:main.path, includeIf.hasconfig:r.u:**.path, etc.). The substring between include and path is if.<condition>:, always longer than one character. The 11-character match window cannot align and the test returns false.

/\s*include.path/.test('include.path')                    // true
/\s*include.path/.test('includeif.gitdir:.path')          // false
/\s*include.path/.test('includeif.onbranch:main.path')    // false

The argv parser at packages/argv-parser/src/argv/analyse-config.ts correctly recognises both include.path=... and includeIf.gitdir:.path=... as config writes; both yield a ConfigWrite with the lowercased key. The defect is purely in the denylist regex (after PR #1167) and in the entry being absent (before PR #1167).

Exploitation chain

  1. Attacker writes a gitconfig to any path the simple-git process can read. Realistic write primitives: file upload (avatar, attachment, CI artifact, S3-mounted bucket), shared /tmp in multi-tenant runners, log poisoning that lands [core] headers in a log path, predictable artifact paths, container volume mounts the attacker controls.

    [core]
    sshCommand = "/bin/sh -c 'id > /tmp/pwned; touch /tmp/RCE'"
    
  2. Attacker triggers git.clone() with crafted customArgs. Either the URL or the customArgs flow from attacker-influenced input. This is…

Record
GHSA-g4wm-2vf7-vfgr
CVSS 3.1
8.1 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-77, CWE-78
Updated
2026-11-02
NVD 8.1

simple-git, an interface for running git commands in any node.js application, enables applications to execute Git operations from JavaScript. Prior to 4.0.0, the default blockUnsafeOperationsPlugin does not completely reject configuration includes supplied through customArgs to git.clone(). The missing include.path classification permits Git to load an attacker-controlled configuration file, and the initial remediation does not cover includeIf.<condition>.path, allowing the same file-loading primitive through a conditional include. A loaded configuration can set an executable Git option such as core.sshCommand, which Git invokes during the clone operation with the privileges of the Node.js process. Exploitation requires the application to pass attacker-influenced custom arguments and requires an attacker-controlled file that the process can read. This issue is fixed in 4.0.0.

Record
CVE-2026-102826
CVSS 3.1
8.1 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-77, CWE-78
Updated
2026-11-02
OSV 8.1

simple-git allows command execution through unblocked Git configuration includes

simple-git, an interface for running git commands in any node.js application, enables applications to execute Git operations from JavaScript. Prior to 4.0.0, the default blockUnsafeOperationsPlugin does not completely reject configuration includes supplied through customArgs to git.clone(). The missing include.path classification permits Git to load an attacker-controlled configuration file, and the initial remediation does not cover includeIf.<condition>.path, allowing the same file-loading primitive through a conditional include. A loaded configuration can set an executable Git option such as core.sshCommand, which Git invokes during the clone operation with the privileges of the Node.js process. Exploitation requires the application to pass attacker-influenced custom arguments and requires an attacker-controlled file that the process can read. This issue is fixed in 4.0.0.

Record
CVE-2026-102826
CVSS 3.1
8.1 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-77, CWE-78
Updated
2026-11-02
OSVGHSA-g4wm-2vf7-vfgr 8.1

simple-git allows command execution through unblocked Git configuration includes

Summary

An OS command injection vulnerability in git.clone() allows any application that flows attacker-influenced data into customArgs to execute arbitrary code. simple-git 3.36.0 (current latest on npm) ships without any include.path entry in the blockUnsafeOperationsPlugin denylist. Passing -c include.path=<file> via customArgs loads any local file as a gitconfig. The loaded file can set core.sshCommand (or any otherwise-denied key), and the next remote operation in the same clone executes the attacker's command.

PR #1167 (merged to main 2026-05-10, not yet released to npm) adds preventConfigBuilder('include.path', 'allowUnsafeInclude') to the denylist. The generated regex /\s*include.path/ closes the plain spelling but does not match the conditional form includeIf.<cond>.path. The variant therefore survives the upcoming release if the regex is not tightened in the same cycle.

This sits in the same denylist class as the prior incomplete-fix chain (CVE-2022-24433, CVE-2022-24066, CVE-2022-25912, CVE-2022-25860, CVE-2026-28291, CVE-2026-28292). include and includeIf are not referenced in any published advisory, in any commit prior to PR #1167, or anywhere in the 3.36.0 source.

Details

Two sinks share the same root cause: the denylist is incomplete.

Sink A: published 3.36.0 has no include.path entry

packages/argv-parser/src/vulnerabilities/detect-vulnerable-config-writes.ts in the v3.36.0 tag contains no entry for include.path or includeIf.*.path. The argv parser recognises -c include.path=<file> and -c includeIf.<cond>.path=<file> as config writes, but detectVulnerableConfigWrites iterates a denylist that does not include either key. The plugin returns no vulnerability and the operation proceeds.

Sink B: pending PR #1167 regex misses includeIf

PR #1167 adds:

const preventUnsafeConfig = [
   // ...
   preventConfigBuilder('include.path', 'allowUnsafeInclude'),
   // ...
];

preventConfigBuilder constructs a non-anchored regex from the string:

function preventConfigBuilder(config, category, message) {
   const regex = typeof config === 'string'
      ? new RegExp(`\\s*${config.toLowerCase()}`)
      : config;
   return function preventCommand(key) {
      if (regex.test(key)) { /* throw */ }
   };
}

For 'include.path', the generated regex is /\s*include.path/. The . between include and path is a regex wildcard. The engine matches include plus exactly one arbitrary character plus path. Conditional include keys have the form includeIf.<condition>.path (includeIf.gitdir:.path, includeIf.onbranch:main.path, includeIf.hasconfig:r.u:**.path, etc.). The substring between include and path is if.<condition>:, always longer than one character. The 11-character match window cannot align and the test returns false.

/\s*include.path/.test('include.path')                    // true
/\s*include.path/.test('includeif.gitdir:.path')          // false
/\s*include.path/.test('includeif.onbranch:main.path')    // false

The argv parser at packages/argv-parser/src/argv/analyse-config.ts correctly recognises both include.path=... and includeIf.gitdir:.path=... as config writes; both yield a ConfigWrite with the lowercased key. The defect is purely in the denylist regex (after PR #1167) and in the entry being absent (before PR #1167).

Exploitation chain

  1. Attacker writes a gitconfig to any path the simple-git process can read. Realistic write primitives: file upload (avatar, attachment, CI artifact, S3-mounted bucket), shared /tmp in multi-tenant runners, log poisoning that lands [core] headers in a log path, predictable artifact paths, container volume mounts the attacker controls.

    [core]
    sshCommand = "/bin/sh -c 'id > /tmp/pwned; touch /tmp/RCE'"
    
  2. Attacker triggers git.clone() with crafted customArgs. Either the URL or the customArgs flow from attacker-influenced input. This is…

Record
GHSA-g4wm-2vf7-vfgr
CVSS 3.1
8.1 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-77, CWE-78
Updated
2026-11-02
OSVCLSA-2026-1791293888 No score

TuxCare security update for simple-git (2 CVEs)

TuxCare rebuilt simple-git to address 2 CVEs. Fixed in 3.36.0-tuxcare.1.

Record
CLSA-2026-1791293888
Updated
2026-11-02
OSVCLSA-2026-1792758525 No score

TuxCare security update for @simple-git/argv-parser (3 CVEs)

TuxCare rebuilt @simple-git/argv-parser to address 3 CVEs. Fixed in 1.1.1-tuxcare.2.

Record
CLSA-2026-1792758525
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
simple-git
npm
through 3.36.0
4.0.0
simple-git
TuxCare:npm
From an advisory covering 2 CVEs
3.36.0-tuxcare.0 up to 3.36.0-tuxcare.1, plus listed versions
3.36.0
3.36.0-tuxcare.1
@simple-git/argv-parser
TuxCare:npm
From an advisory covering 3 CVEs
1.1.1-tuxcare.0 up to 1.1.1-tuxcare.2, plus listed versions
1.1.11.1.1-tuxcare.1
1.1.1-tuxcare.2
simple-git
npm
before 4.0.0
4.0.0

Public exploits

Links only. Every CVE stores no exploit code.

Public exploits
SourceLinkDate
PoC in GitHubCompleteTech-Security/simple-git-rce-check2026-10-23

History

History
RecordedChangedSources
affected, aliases
affected
affected, factsOSV
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV, PoC in GitHub

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-102826 is a high vulnerability (CVSS 8.1) in Simple-git Project Simple-git, published September 29, 2026. Public exploit code exists. EPSS puts the chance of exploitation in the next 30 days at 0.46%, the 40th percentile. Fixed in simple-git 4.0.0.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open