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-2RX9-3G3H-C2JV

GHSA-2rx9-3g3h-c2jv: Path Traversal Vulnerability in pacquet Lockfile Parser and Filesystem Sinks

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 1, 2026·5 min read·12 visits

Executive Summary (TL;DR)

A path traversal vulnerability in pacquet allows unauthenticated remote code execution or file writes outside the workspace boundary via a crafted lockfile when using the --trust-lockfile parameter.

A directory traversal vulnerability exists in pacquet, the Rust port of pnpm. When executing an install with the --trust-lockfile flag enabled, a crafted pnpm-lock.yaml file bypasses resolution-policy verification. This allows an attacker to inject path traversal sequences into package names or versions, leading to symbolic links being written outside the workspace directory.

Vulnerability Overview

The package manager pacquet, which serves as the Rust-based port of pnpm, contains a directory traversal vulnerability. This flaw resides in the processing pipeline of the project lockfile (pnpm-lock.yaml) during dependency materialization.

Under normal execution, the package manager resolves, downloads, and structures dependencies inside a local virtual store, historically located at node_modules/.pnpm. If a user executes an installation with the --trust-lockfile configuration flag, the system skips standard resolution-policy checks.

An attacker who can influence the lockfile contents can inject path traversal sequences such as ../ into package dependency aliases, names, or version properties. Because of the missing validation, the tool performs unsafe path constructions, writing symbolic links outside the project boundary.

Root Cause Analysis

The vulnerability stems from three interrelated software weaknesses: improper pathname limitation (CWE-22) in the dependency name parser, unsafe join operations on the filesystem, and a security verification bypass triggered by CLI optimizations.

First, pacquet parses dependency names and version identifiers from the importers, packages, and snapshots blocks of pnpm-lock.yaml. Historically, the parsing functions failed to validate these strings against typical registry naming standards, which disallow directory traversal tokens. Consequently, malicious input like ../../escaped-link@1.0.0 was successfully serialized into internal memory representations.

Second, the virtual directory layouter and hoisting subsystems used raw pathname joins. Specifically, routines in create_symlink_layout.rs joined local store paths directly with the unvalidated dependency string using std::path::Path::join. This API does not prevent directory breakouts if the right-hand operand contains absolute paths or parent directory indicators.

Third, the flag --trust-lockfile skips lockfile validation. In vulnerable versions, structural safety checks on dependency names were incorrectly bound inside the policy verification process. Disabling policy verification disabled all name checks, removing the final layer of input sanitization.

Code Analysis

Prior to the fix, the virtual store layout engine performed raw string conversions and path concatenation without verifying the bounds of the destination folder.

// Vulnerable pattern in create_symlink_layout.rs
let target_name_str = target.name.to_string();
let alias_name_str = alias_name.to_string();
symlink_package(
    &layout.slot_dir(&target).join("node_modules").join(&target_name_str),
    &virtual_node_modules_dir.join(&alias_name_str),
)

If either target_name_str or alias_name_str is manipulated to contain path traversal components, the resulting directories resolve outside of the restricted virtual store.

The official fix in commit 51300fd41c5e4c8f47635108e373cc3d1f324fa7 implements a containment-checking helper function safe_join_modules_dir to secure filesystem sinks. It also extracts a separate validation pass verify_lockfile_dependency_names that runs unconditionally during frozen installations.

// Patched logic in install_frozen_lockfile.rs
pacquet_lockfile_verification::verify_lockfile_dependency_names(lockfile)
    .map_err(InstallFrozenLockfileError::LockfileVerification)?;

This validator systematically rejects any dependency alias or key containing parent directory traversals, registry delimiters, or reserved directory names such as node_modules or .bin before creating any files on disk.

Exploitation Methodology

To execute this attack, an adversary must commit a crafted pnpm-lock.yaml file to a repository and convince a victim developer or continuous integration (CI) workflow to execute an installation with --trust-lockfile.

The attacker crafts the lockfile by injecting a path traversal sequence into the packages and snapshots sections, mapping a targeted dependency alias to an out-of-bounds destination. The snippet below illustrates a malicious lockfile structure designed to target parent pathways:

lockfileVersion: '9.0'
importers:
  .:
    dependencies:
      '@pnpm.e2e/hello-world-js-bin':
        specifier: 1.0.0
        version: 1.0.0
packages:
  '@pnpm.e2e/hello-world-js-bin@1.0.0':
    resolution: {integrity: sha512-AAAAAAAAAAAAAAAA...}
  '../../escaped-link@1.0.0':
    resolution: {integrity: sha512-AAAAAAAAAAAAAAAA...}
snapshots:
  '@pnpm.e2e/hello-world-js-bin@1.0.0': {}
  '../../escaped-link@1.0.0': {}

When pacquet install --frozen-lockfile --trust-lockfile is executed, the layout builder processes the malicious package entry. Due to skipped policy checks, the engine executes the raw path join using the string ../../escaped-link@1.0.0. The operating system then creates a symlink in the parent workspace directory, permitting arbitrary directory writes or execution redirection.

Impact Assessment

The impact of this path traversal is significant, particularly in automated environments and shared developer workstations. Although exploiting this vulnerability requires the presence of a modified lockfile and specific CLI arguments, the potential consequences of successful exploitation are substantial.

First, because the vulnerability allows the creation of symbolic links outside the directory structure of the project, an attacker can manipulate files in sensitive directories relative to the workspace. This can be used to overwrite configurations or hijack command executors.

Second, in CI/CD pipelines, this flaw can bypass repository isolation. A malicious pull request can modify the lockfile, breakout of the build directory, and read or write files across the runner's shared filesystem, exposing secrets, API keys, or deployment tokens.

Lastly, combined with local dependency resolution mechanics, the symbolic links can point to executable binaries in other system paths. This provides an attacker with a vector to achieve remote code execution (RCE) on the developer host or CI agent.

Mitigation and Remediation

To remediate this vulnerability, upgrade pnpm and the underlying pacquet binaries to a version that includes the structural lockfile verification patch in commit 51300fd41c5e4c8f47635108e373cc3d1f324fa7.

If patching is not immediately feasible, you can prevent exploitation by disabling the --trust-lockfile configuration flag across all build and local scripts. Enforcing strict lockfile verification ensures that standard resolution-policy checkers flag anomalous structure variations.

Additionally, integrate static lockfile linter rules into CI pipelines. Pre-commit hooks can scan pnpm-lock.yaml files for any relative path segments (../ or ..\) inside package keys and snapshot definitions to prevent malicious changes from being merged into the master branch.

Fix Analysis (1)

Technical Appendix

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

Affected Systems

pacquet (Rust-based package manager port for pnpm)pnpm (when executing pacquet install components)

Affected Versions Detail

Product
Affected Versions
Fixed Version
pnpm (pacquet)
pnpm
Prior to Commit 51300fd41c5e4c8f47635108e373cc3d1f324fa7Commit 51300fd41c5e4c8f47635108e373cc3d1f324fa7
AttributeDetail
CWE IDCWE-22
Attack VectorLocal/Network via Crafted Lockfile
CVSS v3.1 Score8.1
Exploit Statuspoc
Affected Flag--trust-lockfile
ImpactArbitrary Symlink Creation & File Write Outside Project Directory
Fix Commit51300fd41c5e4c8f47635108e373cc3d1f324fa7

MITRE ATT&CK Mapping

T1072Software Deployment
Execution
T1190Exploit Public-Facing Application
Initial Access
CWE-22
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

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

References & Sources

  • [1]GitHub Security Advisory GHSA-2RX9-3G3H-C2JV
  • [2]pnpm Repository Advisory GHSA-2rx9-3g3h-c2jv
  • [3]Associated Pull Request #12872
  • [4]Official Fix Commit

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

•2 minutes ago•CVE-2026-109619
9.2

CVE-2026-109619: Remote Code Execution in PHP Core via Stale Global State Memory Corruption (PHP2Shell)

CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.

Alon Barad
Alon Barad
1 views•6 min read
•5 minutes ago•CVE-2026-113721
4.5

CVE-2026-113721: Unsafe Link Resolution in virtualenv File Generation

In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.

Amit Schendel
Amit Schendel
1 views•5 min read
•9 days ago•CVE-2026-87697
8.8

CVE-2026-87697: Untrusted Deserialization in .NET PresentationCore Clipboard Handling

A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.

Alon Barad
Alon Barad
31 views•5 min read
•9 days ago•CVE-2026-70007
8.8

CVE-2026-70007: Out-of-Bounds Write Vulnerability in .NET Framework and WPF Subsystem

An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.

Amit Schendel
Amit Schendel
19 views•6 min read
•10 days ago•CVE-2026-70186
7.5

CVE-2026-70186: ASP.NET Core Denial of Service Vulnerability via Framework Deadlock

ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.

Amit Schendel
Amit Schendel
18 views•5 min read
•10 days ago•CVE-2026-70035
8.8

CVE-2026-70035: Insecure Deserialization Remote Code Execution in Microsoft .NET Framework and .NET Runtime

CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.

Amit Schendel
Amit Schendel
24 views•6 min read