Deno: BYONM module resolution allows `package.json` main path traversal to bypass `--allow-read` restrictions
Date: 2026-06
Affected: rust/deno
Attack vector: path-traversal
Category: vulnerability-disclosure
Severity: Medium
CVE: CVE-2026-49406
CWE: CWE-22
CVSS: 5.5 (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N)

## Summary When Deno was run in BYONM mode (`nodeModulesDir: "manual"`), the module resolver did not validate that a package's resolved entrypoint stayed within its `node_modules/<pkg>/` directory. A malicious `package.json` whose `main` field contained `..` segments was able to resolve to an arbitrary path on disk, and the resolver then read that file without consulting the `--allow-read` allowlist. This let a `require("evil-pkg")` call return the contents of a file that a direct `Deno.readTextFileSync(...)` call would have been blocked from reading. ## Details In BYONM mode, Deno resolved npm packages directly from a user-managed `node_modules` tree. Resolution of `require("pkg")` proceeded by reading `pkg/package.json`, taking the `main` field, joining it to the package directory, and loading the result as a module. The path joined from `main` was not constrained to the package root. A `package.json` such as: ```json { "main": "../../../secret.json" } ``` resolved to `node_modules/pkg/../../../secret.json`, escaping `node_modules` entirely. The BYONM permission check accepted any path that contained a `node_modules` component and did not reject `..` traversal, so the resolved path was loaded without a read-permission check. Because resolution loaded JSON entrypoints by parsing their contents and returning them through `require`, this exposed the contents of arbitrary `.json` files reachable by the OS user to the requiring code, even when `--allow-read` had been narr


Mitigations:

Architectural layers (MAESTRO):