Executive brief
pnpm is a fast Node.js package manager used by developers to install and manage project dependencies. When removing a globally-installed package, pnpm can be tricked into deleting critical system directories if the package contains specially-crafted bin entries with reserved names like ".." (parent directory). An attacker can distribute a malicious package that, once uninstalled globally, destroys the pnpm installation directory itself, preventing further package management operations.
Technical details
The vulnerability is a path traversal flaw in pnpm's global package removal flow (CWE-22, CWE-73). The bins/resolver component accepts reserved bin names (empty string, ".", "..") that bypass validation checks for URL-safe text. When global remove, update, or add-replacement commands scan installed manifests and call path.join(globalBinDir, binName), reserved names cause path traversal: "." targets the global bin directory itself, ".." targets its parent. The removal sink (bins/remover/removeBins.ts) recursively deletes the resulting path. Install-time checks do not prevent this because conflict validation occurs on an already-escaped path and does not reject reserved segments. Attack requires a user to globally install a malicious package, then issue pnpm global remove. The fix (patched in pnpm 10.34.2 and 11.5.3+) validates and rejects reserved bin names in the resolver after scope stripping.
Affected products
- pnpm pnpm <10.34.2 and >=11.0.0 <11.5.3
Timeline
- 2026-06-26: disclosed
- 2026-06-26: patched: pnpm 10.34.2 and 11.5.3+