GHSA-p4xf-rf54-rj3x

Suggest an improvement
Source
https://github.com/advisories/GHSA-p4xf-rf54-rj3x
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-p4xf-rf54-rj3x/GHSA-p4xf-rf54-rj3x.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-p4xf-rf54-rj3x
Aliases
  • CVE-2026-50014
Published
2026-06-26T22:53:21Z
Modified
2026-06-26T23:00:16.836317601Z
Severity
  • 6.4 (Medium) CVSS_V3 - CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:H/A:N CVSS Calculator
Summary
pnpm: Git Fetch Argument Injection via Lockfile resolution.commit
Details

Summary

pnpm passes the lockfile-controlled git resolution.commit value to git fetch without a -- separator or commit-format validation. For git dependencies fetched through the shallow-fetch path, a malicious lockfile can replace the expected 40-character commit hash with a Git option such as --upload-pack=<command>. For SSH and local transports, --upload-pack can execute the supplied command. HTTPS transports ignore --upload-pack, so the practical attack surface is primarily SSH or local git dependencies.

Vulnerability Details

The vulnerable path is in fetching/git-fetcher/src/index.ts. When a git dependency host is configured for shallow fetching, pnpm calls:

await execGit(['fetch', '--depth', '1', 'origin', resolution.commit], { cwd: tempLocation })

Because resolution.commit is appended before a -- separator, Git can parse a commit value beginning with - as an option. The same file later passes the value to git checkout without a separator:

await execGit(['checkout', resolution.commit], { cwd: tempLocation })

resolution.commit comes from the lockfile and is typed as a plain string; pnpm does not validate it as a 40-character hexadecimal commit before passing it to Git.

Proof of Concept

bash autofyn_audit/exploits/vuln11_git_upload_pack_rce/exploit.sh
# Creates a local bare git repo and triggers the shallow-fetch path.
# Replaces the lockfile commit hash with '--upload-pack=touch /tmp/vuln11_pwned'.
# Result: PASS -- /tmp/vuln11_pwned created by injected touch command.

The PoC uses a local file://githost/... repository because the injection requires a local or SSH transport. HTTPS transport ignores --upload-pack.

Impact

Code execution as the user running pnpm install, under specific transport conditions. The attacker must modify pnpm-lock.yaml, and the affected dependency must use SSH or local git transport. HTTPS transport (the common case) is immune.

Suggested Remediation

Add a -- separator before lockfile-controlled git revision values. Validate resolution.commit matches /^[0-9a-f]{40}$/i before passing to Git.


Discovered by AutoFyn Full audit report: audit_report.md Exploit script: exploit.sh

Database specific
{
    "nvd_published_at": "2026-06-25T18:16:39Z",
    "cwe_ids": [
        "CWE-88"
    ],
    "github_reviewed": true,
    "severity": "MODERATE",
    "github_reviewed_at": "2026-06-26T22:53:21Z"
}
References

Affected packages

npm / pnpm

Package

Affected ranges

Type
SEMVER
Events
Introduced
0Unknown introduced version / All previous versions are affected
Fixed
10.34.0

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-p4xf-rf54-rj3x/GHSA-p4xf-rf54-rj3x.json"

npm / pnpm

Package

Affected ranges

Type
SEMVER
Events
Introduced
11.0.0
Fixed
11.4.0

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-p4xf-rf54-rj3x/GHSA-p4xf-rf54-rj3x.json"