Sep 1, 2026·5 min read·4 visits
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.
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.
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.
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.
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.
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.
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.
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
pnpm (pacquet) pnpm | Prior to Commit 51300fd41c5e4c8f47635108e373cc3d1f324fa7 | Commit 51300fd41c5e4c8f47635108e373cc3d1f324fa7 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 |
| Attack Vector | Local/Network via Crafted Lockfile |
| CVSS v3.1 Score | 8.1 |
| Exploit Status | poc |
| Affected Flag | --trust-lockfile |
| Impact | Arbitrary Symlink Creation & File Write Outside Project Directory |
| Fix Commit | 51300fd41c5e4c8f47635108e373cc3d1f324fa7 |
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.
An authentication oracle vulnerability exists in Filament before 4.12.5 and 5.7.5. The application initiates MFA challenge workflows prior to verifying user authorization policies, allowing unauthenticated attackers to validate guessed credentials.
A multi-factor authentication bypass vulnerability exists in Filament (Laravel full-stack framework panels) due to improper time-step tracking of Time-Based One-Time Password (TOTP) codes. By submitting valid TOTP codes from an older time window within the drift allowance, an attacker with a user's password can bypass the single-use MFA guarantee and obtain unauthorized account access.
CVE-2026-19418 is a high-severity origin validation vulnerability in TYPO3 CMS that enables Cross-Site Request Forgery (CSRF) and access control bypasses. Due to architectural consolidation of entry points in version 13.0, the core ReferrerEnforcer fails to isolate backend endpoints from the frontend, allowing an attacker with frontend script execution capabilities to perform unauthorized administrative actions.
CVE-2026-84304 is a high-severity uncontrolled resource consumption vulnerability in gRPC-Go, the Go implementation of the gRPC framework. The issue stems from a memory amplification flaw inside the HTTP/2 DATA frame processing subsystem. Remote, unauthenticated attackers can exploit this vulnerability by sending a high volume of heavily fragmented, tiny DATA frames within multiplexed concurrent streams. This causes gRPC-Go servers to allocate excessive internal metadata structures on the Go heap, leading to severe heap memory amplification, intense garbage collection thrashing, and process termination due to Out-of-Memory (OOM) conditions.
CVE-2026-79675 is a critical command injection vulnerability in NLTK versions prior to 3.10.3 that permits remote attackers to execute arbitrary code on the hosting system. This vulnerability stems from an incomplete mitigation of a previous vulnerability, CVE-2026-12841. While NLTK verified global JVM options configured through the library's setup routines, it failed to perform equivalent safety checks on options provided during per-call invocations of Stanford NLP Java wrappers. Attackers controlling these parameters can pass dangerous Java configuration options to the system shell, bypassing security boundaries to spawn interactive processes or load untrusted Java archives.
A vulnerability in Django REST Framework (DRF) before version 3.17.2 allows remote attackers to bypass the native Django DATA_UPLOAD_MAX_MEMORY_SIZE limits. When parsing JSON or URL-encoded request bodies, DRF's JSONParser and FormParser read directly from the low-level HTTP network stream, bypassing Django's high-level request size checks and causing Denial of Service (DoS) via resource exhaustion.