Deno: BYONM module resolution allows `package.json` main path traversal to bypass `--allow-read` restrictions
Description
In BYONM mode, Deno's module resolver did not validate path traversal in a package's main field, allowing arbitrary file reads without checking --allow-read permissions.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
In BYONM mode, Deno's module resolver did not validate path traversal in a package's `main` field, allowing arbitrary file reads without checking `--allow-read` permissions.
Vulnerability
When Deno was used with the BYONM (Bring Your Own node_modules) feature enabled (nodeModulesDir: "manual"), the module resolver resolved npm packages directly from a user-managed node_modules tree. When resolving a require("pkg") call, the resolver read the main field from the package's package.json, joined it to the package directory, and loaded the result as a module. However, the resolver did not validate that the resolved path remained within the package's node_modules// directory. A malicious package.json whose main field contained .. segments (e.g., "../../../secret.json") could traverse upward, escaping the package root and even the node_modules directory entirely. This affected any Deno version that supports BYONM mode with nodeModulesDir: "manual" before the fix. [1][2]
Exploitation
To exploit this vulnerability, an attacker must be able to introduce a malicious npm package into the node_modules tree used by a Deno application running in BYONM mode. This could occur through a compromised dependency or a direct addition to the project. No special network position or authentication is required beyond the ability to place the package. The attacker creates a package.json with a main field containing path traversal sequences pointing to a target file (e.g., "../../secret.json"). When the Deno application executes require("evil-pkg"), the resolver reads the attacker-controlled package.json, constructs the path by joining the package directory (node_modules/evil-pkg/) with the traversal sequence, and loads the resulting file. The BYONM permission check at the time only verified that the path contained a node_modules component, which was still true after traversal, so the file was read without consulting the --allow-read allowlist. [1][2]
Impact
A successful attack allows an unprivileged actor to read arbitrary files on the filesystem that the OS user can access, bypassing the --allow-read permission restrictions. This violates the confidentiality of sensitive data such as secrets, configuration files, or any .json file (the PoC specifically targeted JSON files because the resolver parsed JSON entrypoints). The attacker cannot directly achieve code execution or write files, but reading sensitive data can lead to further compromise (e.g., credential theft). The scope is limited to files reachable by the OS user; the same file accessed via a direct Deno.readTextFileSync() call would have been correctly blocked. [1][2]
Mitigation
The vulnerability was fixed in Deno version 2.2.0, released on 2025-02-25. Users running Deno with BYONM mode (nodeModulesDir: "manual") are strongly advised to upgrade to that version or later. For those unable to upgrade immediately, the only workaround is to disable BYONM mode (i.e., use a different nodeModulesDir setting such as "auto" or rely on Deno's built-in vendoring) and ensure that the execution environment is free of untrusted packages. Affected Deno versions are not on the CISA KEV list as of this writing. [1][2]
AI Insight generated on Jun 16, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
0No patches discovered yet.
Vulnerability mechanics
Root cause
"Missing path traversal validation in BYONM module resolver allows `package.json` `main` field with `..` segments to escape `node_modules` and bypass `--allow-read` restrictions."
Attack vector
An attacker who controls an npm package installed in a BYONM `node_modules` tree sets the `main` field in `package.json` to a path with `..` segments (e.g. `"../../secret.json"`). When the victim's code calls `require("evil-pkg")`, the resolver joins that `main` value to the package directory, producing a path that escapes `node_modules` entirely. The BYONM permission check only verifies that the path contains a `node_modules` component and does not block `..` traversal, so the resolved file is read without consulting the `--allow-read` allowlist [ref_id=1][ref_id=2].
Affected code
The BYONM module resolver in `nodeModulesDir: "manual"` mode did not constrain the path resolved from a package's `package.json` `main` field to the package's own `node_modules/<pkg>/` directory. The resolver joined the `main` value to the package directory without rejecting `..` traversal, allowing escape from `node_modules`.
What the fix does
The advisory does not include a published patch diff. The recommended fix is to validate that the resolved entrypoint path stays within the package's own `node_modules/<pkg>/` directory, rejecting any `..` segments that would escape that boundary. The module resolver must also enforce the same `--allow-read` permission check that the filesystem APIs enforce, so that a path resolved through `require()` is subject to the same allowlist as a direct `Deno.readTextFileSync()` call [ref_id=1][ref_id=2].
Preconditions
- configDeno must be run with BYONM mode enabled (`nodeModulesDir: "manual"`)
- inputA malicious npm package with a `package.json` `main` field containing `..` segments must be installed in `node_modules`
- inputThe victim's code must call `require("evil-pkg")`
- config`--allow-read` must be set to a restricted scope that excludes the target file
Generated on Jun 16, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.