CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-QRV3-253H-G69C

GHSA-QRV3-253H-G69C: Path Traversal and Arbitrary Symlink Creation via configDependencies in pnpm

Amit Schendel
Amit Schendel
Senior Security Researcher

Jun 27, 2026·7 min read·19 visits

Executive Summary (TL;DR)

A path traversal vulnerability in pnpm's configDependencies handling allows malicious lockfiles to create arbitrary directories and symbolic links outside of node_modules, bypassing the execution boundaries of --ignore-scripts during package installation.

A high-severity path traversal vulnerability exists in the pnpm package manager. By crafting a malicious lockfile (pnpm-lock.yaml) with path traversal characters in the configDependencies block, an attacker can create arbitrary directories and symlinks outside the project's node_modules/.pnpm-config directory. This exploitation happens automatically during pnpm installation, even when executing with scripts disabled via the --ignore-scripts flag.

Vulnerability Overview & Attack Surface Analysis

The pnpm package manager utilizes a unique virtual store layout inside node_modules/.pnpm and manages global packages using hard links to minimize disk space consumption. To support environment-specific properties and isolated configuration setups, the pnpm lockfile format (pnpm-lock.yaml) implements a configDependencies section. Under standard operational conditions, these configurations are isolated under a dedicated subdirectory: node_modules/.pnpm-config.

Because the installer processes dependencies declared in local workspace lockfiles under the assumption that they represent validated states, the keys and version strings within this configuration section are parsed directly to build directory trees. When users clone and inspect open-source or third-party repositories, they run installation commands to configure local packages. The installation stage represents a significant security boundary because it executes code before manual inspection can occur.

To limit risks associated with third-party software, security frameworks and automated testing pipelines often enforce the --ignore-scripts flag during installation to block life-cycle script executions (e.g., preinstall, postinstall). However, this path traversal bypasses those blocks. Because the installation code path itself handles the generation of these directory hierarchies, directory creation and symbolic link mapping occur regardless of whether script execution is restricted or disabled.

Root Cause Analysis of Path Traversal

The root cause of this vulnerability lies in the lack of validation and sanitization of user-controlled parameters extracted from configDependencies during workspace setup. In vulnerable versions, pnpm reads the package names and version keys declared inside pnpm-lock.yaml and directly utilizes them to construct output filesystem paths using Node.js's standard utility function path.join.

The application constructs the output configuration workspace using a base path defined as const configModulesDir = path.join(opts.rootDir, 'node_modules/.pnpm-config'). When iterating over the keys in the dependency structure, pnpm evaluates path.join(configModulesDir, pkgName). Because Node.js's path.join resolves relative directory segments natively, any package name containing upward path traversal sequences (such as ../../) will escape the restricted base directory.

This behavior means that instead of creating directories and mapping links inside the protected node_modules/.pnpm-config directory, pnpm evaluates the destination path relative to the workspace root or the wider host filesystem depending on the number of traversal sequences used. The application then proceeds to execute the directory creation and symlink linkage (symlinkDir) using these resolved out-of-bounds target destinations, allowing arbitrary system structures to be modified or created based solely on the contents of the lockfile.

Code-Level Patch & Verification Analysis

The vulnerability was resolved by introducing explicit strict validations within the package installer's parsing flow. The fix, implemented in commit 352ae489f1b14ffdc19d2c6eacb1b06b098c2ddc, adds verification checks that validate both the configuration names and versions before any path processing or folder creation functions are invoked.

Specifically, the patch enforces validation in normalizeConfigDeps.ts using two new assertion files: assertValidConfigDepName.ts and assertValidConfigDepVersion.ts. Below is the logical implementation introduced to validate names:

// config/deps-installer/src/assertValidConfigDepName.ts
import { PnpmError } from '@pnpm/error'
import validateNpmPackageName from 'validate-npm-package-name'
 
export function assertValidConfigDepName (name: string): void {
  // Verify that the dependency name conforms to legitimate npm package name standards
  if (!validateNpmPackageName(name).validForOldPackages) {
    throw new PnpmError(
      'INVALID_DEPENDENCY_NAME',
      `The configDependencies in pnpm-workspace.yaml contains a dependency with an invalid name: ${JSON.stringify(name)}`,
      {
        hint: 'A dependency name must be a valid npm package name — a single `name` or `@scope/name` consisting of URL-friendly characters, with no leading `.` or `_`, and not equal to reserved names such as `node_modules`.',
      }
    )
  }
}

Additionally, the patch enforces that the configuration versions match exact semantic version formats (semver) to prevent an attacker from nesting directory traversal sequences in the version fields. This validation prevents attackers from exploiting variables used to organize the virtual store folders:

// config/deps-installer/src/assertValidConfigDepVersion.ts
import { PnpmError } from '@pnpm/error'
import semver from 'semver'
 
export function assertValidConfigDepVersion (name: string, version: string): void {
  // Block non-semver compliant characters (preventing traversal inside version strings)
  if (semver.valid(version) == null) {
    throw new PnpmError(
      'INVALID_CONFIG_DEP_VERSION',
      `The config dependency "${name}" has an invalid version "${version}"`,
      { hint: 'A config dependency version must be an exact semver version.' }
    )
  }
}

These checks guarantee that characters like . and / cannot be leveraged inside configuration dependency identifiers, thereby resolving the path traversal vulnerability. The fix is considered complete because it restricts inputs to safe, standardized schemas (npm package names and SemVer specs) before they reach any filesystem sink.

Exploitation Mechanics & Payload Engineering

An attacker targets this vulnerability by modifying a project's pnpm-lock.yaml file to inject path traversal structures into the keys mapped within the configDependencies block. The target project is then uploaded to a version control hosting service or distributed through standard channels, waiting for a victim or automated system to run an installation command.

importers:
  .:
    configDependencies:
      legit-config-dep:
        specifier: '1.0.0'
        version: '1.0.0'
      '../../PWNED_CFGDEP':
        specifier: '1.0.0'
        version: '1.0.0'

When a victim clones the repository and runs pnpm install, the installer parses the configuration structures and triggers path resolution. This execution path is represented by the following logical process flow:

Once the path resolution completes, the installer executes filesystem changes to map the cache directory to the local folder. If an attacker directs the path traversal to critical targets, they can create and link to folders that manipulate or overlay development settings, build configurations, or localized tooling directories.

Threat Landscape & Impact Assessment

The impact of this vulnerability is significant for multi-tenant CI/CD systems, automated analysis sandboxes, and developer workstations. In modern software engineering workflows, testing pipelines pull external code and run pnpm install automatically to construct test environments. Even when administrators disable post-install scripting mechanisms, the creation of arbitrary directories and symlinks still proceeds because it occurs inside pnpm's core binary routines.

Because the CVSS vector is rated as CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:L (CVSS Base Score: 8.3), the exploitation of this vulnerability has direct implications for integrity. The Scope Change (S:C) metric is particularly important: it means pnpm can write symbolic links outside of its designated sandbox (the workspace's node_modules directory), potentially affecting parent directories or system-wide configuration folders.

An attacker can utilize this primitive to execute symbolic link overwriting attacks, targeting adjacent folders in shared CI/CD agents or placing malicious symlinks that point to sensitive files. This can lead to local configuration hijacking or unauthorized file writing across build steps, depending on the permissions of the user execution context under which the installer is running.

Detection, Remediation, and Defense-in-Depth

Organizations should prioritize upgrading global and local pnpm installations. To secure systems running active workflows, update the package manager to the designated patched versions: version 10.34.4 or later for the v10 release branch, and version 11.8.0 or later for the v11 release branch.

Security teams can identify potential exploitation attempts in existing repositories by scanning lockfiles for structural path traversal sequences. Using standard command-line tools, administrators can audit codebase histories to detect anomalous entries within the target blocks:

grep -E "configDependencies:" -A 10 pnpm-lock.yaml | grep -E "\.\./"

As a defense-in-depth measure, automated build environments and CI systems should enforce strict engine constraints in project settings, preventing local execution on insecure pnpm runtimes. This configuration can be formalized in the project's package.json file to block installation attempts if an obsolete version is detected:

"engines": {
  "pnpm": ">=11.8.0"
}

Official Patches

pnpmFix patch commit introduced to validate configDependencies
pnpmRelease notes for version 11.8.0
pnpmRelease notes for version 10.34.4

Fix Analysis (1)

Technical Appendix

CVSS Score
8.3/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:L

Affected Systems

pnpm package manager for Node.js

Affected Versions Detail

Product
Affected Versions
Fixed Version
pnpm
pnpm
>= 0 < 10.34.410.34.4
pnpm
pnpm
>= 11.0.0 < 11.8.011.8.0
AttributeDetail
CWE IDCWE-22
Attack VectorNetwork (AV:N)
CVSS v3.1 Score8.3
EPSS ScoreN/A
ImpactIntegrity (High)
Exploit StatusProof of Concept (PoC) Available
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1036Masquerading
Defense Evasion
T1222.002File and Directory Permissions Modification: Linux and Mac Permissions
Defense Evasion
T1059Command and Scripting Interpreter
Execution
CWE-22
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The software uses external input to construct a pathname that is intended to identify a file or directory that is located beneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location outside of the restricted directory.

Known Exploits & Detection

GitHub Security AdvisoryExploit methodology and execution summary detail showing the traversal behavior of configuration installer keys.

Vulnerability Timeline

Vulnerability fixed internally under commit 352ae48
2026-06-18
Advisory publicly published to GitHub Security Advisory Database
2026-06-27

References & Sources

  • [1]GitHub Security Advisory GHSA-QRV3-253H-G69C
  • [2]pnpm Project Repository
  • [3]OSV Vulnerability Record

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•3 days ago•CVE-2026-71556
7.1

CVE-2026-71556: Symbolic Link Directory Traversal in go-git

A symbolic link directory traversal vulnerability was identified in go-git, a pure Go implementation of the Git specification. This vulnerability allows an attacker to construct a repository that, when checked out or processed, bypasses directory boundaries to write or overwrite arbitrary files on the host filesystem.

Amit Schendel
Amit Schendel
14 views•5 min read
•3 days ago•CVE-2026-71557
6.3

CVE-2026-71557: Path Traversal and Configuration Overwrite in go-git Filesystem Storage Engine

CVE-2026-71557 is a path traversal vulnerability in go-git, a pure-Go implementation of Git. In vulnerable versions, the filesystem-backed storage engine fails to validate reference names before mapping them to on-disk paths. An attacker hosting a malicious Git server can advertise references containing directory traversal sequences, such as 'refs/heads/../../config', to write or overwrite files outside the intended reference storage directory.

Amit Schendel
Amit Schendel
10 views•7 min read
•3 days ago•GHSA-7C4V-FWGW-9RF7
5.3

GHSA-7c4v-fwgw-9rf7: Nuxt Dev Server Discloses Project Root and Workspace UUID via Chrome DevTools Endpoint

An information disclosure vulnerability in the Nuxt development server allows adjacent network attackers to retrieve the absolute project root directory and a persistent workspace UUID by querying the unprotected Chrome DevTools workspace endpoint. This occurs when the development server is bound to a network-reachable interface, allowing requests that bypass the header-based security verification checks.

Alon Barad
Alon Barad
11 views•7 min read
•3 days ago•CVE-2026-66062
5.3

CVE-2026-66062: Regular Expression Denial of Service (ReDoS) in SvelteKit Content Negotiation

A Regular Expression Denial of Service (ReDoS) vulnerability exists in SvelteKit's content negotiation header parser prior to version 2.70.2. An unauthenticated remote attacker can exploit this vulnerability by sending a crafted Accept header with highly repetitive malformed values. This triggers catastrophic backtracking on the single-threaded Node.js/Bun event loop, leading to CPU exhaustion and full denial of service.

Alon Barad
Alon Barad
9 views•6 min read
•3 days ago•CVE-2026-15895
8.4

CVE-2026-15895: OS Command Injection in AWS jsii-diff CLI

An OS command injection vulnerability exists in the npm package loading component of the jsii-diff CLI tool within the AWS jsii framework. Prior to version 1.131.0, when parsing package specifiers prefixed with `npm:`, the tool concatenated user-controlled inputs directly into a shell execution string via child_process.exec. This allows attackers to execute arbitrary shell commands under the context of the running Node.js process.

Amit Schendel
Amit Schendel
7 views•7 min read
•3 days ago•CVE-2026-63220
4.8

CVE-2026-63220: Trust of Untrusted Reverse Proxy Headers in CodeIgniter4

CodeIgniter4 versions prior to v4.7.4 contain a protocol-spoofing vulnerability due to improper verification of upstream reverse proxy forwarding headers. Remote, unauthenticated attackers can inject headers like X-Forwarded-Proto to deceive the framework into identifying an insecure HTTP request as a secure HTTPS connection.

Alon Barad
Alon Barad
15 views•7 min read