Skip to main content
Vulnerability Database/CVE-2026-82392

CVE-2026-82392: pnpm Package Manager RCE Vulnerability

CVE-2026-82392 is a remote code execution vulnerability in pnpm package manager that allows attackers to write package contents outside node_modules and execute code. This post covers technical details, affected versions, impact, and mitigation.

Published:

CVE-2026-82392 Overview

CVE-2026-82392 is a path traversal vulnerability [CWE-22] in pnpm, a widely used JavaScript package manager. Versions prior to 10.34.5 and versions 11.0.0 through 11.11.0 parse attacker-controlled package names from pnpm-lock.yaml without validation. The unsanitized name flows into path.join(modules, pkgName) and storeController.importPackage, allowing package contents to be written outside node_modules when a user runs pnpm install. When dangerouslyAllowAllBuilds or a matching allowBuilds entry permits lifecycle scripts, the escaped package can execute arbitrary code with the invoking user's privileges.

Critical Impact

A malicious lockfile can drop files anywhere the user has write access and, if lifecycle scripts are allowed, achieve code execution during a routine pnpm install.

Affected Products

  • pnpm versions prior to 10.34.5
  • pnpm versions 11.0.0 up to and including 11.10.x
  • Projects consuming untrusted pnpm-lock.yaml files via pnpm install

Discovery Timeline

  • 2026-08-31 - CVE-2026-82392 published to NVD
  • 2026-09-01 - Last updated in NVD database

Technical Details for CVE-2026-82392

Vulnerability Analysis

pnpm resolves each dependency entry in pnpm-lock.yaml by calling dp.parse(depPath).name to extract the package name. The parsed value is trusted and consumed directly by downstream file-system operations in deps/graph-builder/src/lockfileToDepGraph.ts and pnpm11/deps/graph-builder/src/lockfileToDepGraph.ts. Because the name originates from lockfile keys that an attacker controls, a crafted entry can contain traversal sequences such as ../ or absolute path fragments.

The unvalidated name reaches three sinks: path.join(modules, pkgName), storeController.importPackage, and the Plug'n'Play writer in pnpm11/lockfile/to-pnp/src/index.ts. Each sink resolves the path relative to the virtual store or node_modules without confining the result. A supply-chain attacker who can influence a repository's committed lockfile can therefore stage files at arbitrary locations on the developer's or CI runner's filesystem.

Root Cause

The root cause is missing containment on parsed dependency names. pnpm assumed pnpm-lock.yaml keys were well-formed npm package identifiers, but the parser does not reject names that decode into relative-path components. The fix introduces a safeJoinModulesDir helper and a new verify_lockfile_dependency_names() verification pass that rejects names attempting to escape the modules directory.

Attack Vector

Exploitation requires the victim to run pnpm install against a repository containing a malicious pnpm-lock.yaml. The attack is network-adjacent through typical supply-chain vectors: a poisoned public package, a compromised fork, or a pull request that alters the lockfile. Code execution follows only when lifecycle scripts are permitted through dangerouslyAllowAllBuilds or a matching allowBuilds allowlist entry that covers the attacker-controlled name.

typescript
// Patch excerpt: deps/graph-builder/src/lockfileToDepGraph.ts
   type FetchResponse,
   type StoreController,
 } from '@pnpm/store-controller-types'
+import { safeJoinModulesDir } from '@pnpm/symlink-dependency'
 import * as dp from '@pnpm/dependency-path'
 import pathExists from 'path-exists'
 import equals from 'ramda/src/equals'

Source: GitHub Commit 78e29fe

rust
// Patch excerpt: pacquet/crates/package-manager/src/create_symlink_layout.rs
-use crate::{SkippedSnapshots, SymlinkPackageError, VirtualStoreLayout, symlink_package};
+use crate::{
+    SkippedSnapshots, SymlinkPackageError, VirtualStoreLayout,
+    safe_join_modules_dir::safe_join_modules_dir, symlink_package,
+};
 use pacquet_lockfile::{PkgName, SnapshotDepRef};
 use std::{collections::HashMap, path::Path};

Source: GitHub Commit 51300fd

Detection Methods for CVE-2026-82392

Indicators of Compromise

  • pnpm-lock.yaml files containing package keys with ../, ..\, absolute paths, or URL-encoded traversal sequences in the name portion.
  • Files created outside the project's node_modules directory during or immediately after a pnpm install run.
  • Unexpected writes to user profile directories, CI workspace roots, or shell startup files by the pnpm or node process.
  • Lifecycle script execution originating from a package name that does not match a known registry package.

Detection Strategies

  • Scan repositories and pull requests for pnpm-lock.yaml entries whose top-level keys fail a strict npm package-name regex.
  • Compare pre- and post-install filesystem snapshots on CI runners to flag writes outside the project workspace.
  • Alert on pnpm install invocations that spawn child processes writing to paths outside node_modules.
  • Inventory pnpm versions across developer endpoints and build agents; flag any version below 10.34.5 or between 11.0.0 and 11.10.x.

Monitoring Recommendations

  • Enable EDR file-write telemetry on developer workstations and CI hosts, focusing on process ancestry rooted in pnpm or node.
  • Log and review changes to pnpm-lock.yaml in code review, especially in pull requests from forks or first-time contributors.
  • Monitor for the addition of dangerouslyAllowAllBuilds: true or new allowBuilds entries in .npmrc or package.json.

How to Mitigate CVE-2026-82392

Immediate Actions Required

  • Upgrade pnpm to 10.34.5 on the v10 branch or 11.11.0 on the v11 branch across all developer machines and CI runners.
  • Audit recent pnpm-lock.yaml changes for entries containing traversal characters or otherwise malformed package names.
  • Disable dangerouslyAllowAllBuilds and review every entry in allowBuilds to ensure only trusted packages can run lifecycle scripts.
  • Rotate any credentials that were accessible from a workstation or CI job that ran pnpm install against an untrusted lockfile.

Patch Information

The issue is fixed in pnpm 10.34.5 and 11.11.0. The fix, delivered in PR #12872 and backported in PR #12890, introduces safeJoinModulesDir containment for TypeScript code paths and safe_join_modules_dir plus verify_lockfile_dependency_names() in the Rust pacquet crates. Full details are in GHSA-c59q-g84q-2gj5.

Workarounds

  • Run pnpm install --ignore-scripts when working with any lockfile from an untrusted source until upgrading is complete.
  • Execute pnpm install inside an ephemeral container or sandbox with no access to sensitive host paths or credentials.
  • Require signed commits and enforce lockfile review policies so that untrusted contributors cannot modify pnpm-lock.yaml without approval.
bash
# Upgrade pnpm to a fixed release
npm install -g pnpm@10.34.5   # v10 branch
# or
npm install -g pnpm@11.11.0   # v11 branch

# Verify installed version
pnpm --version

# Safer install when reviewing untrusted lockfiles
pnpm install --ignore-scripts

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.