Skip to main content

Deno CVE-2026-49406

| EUVDEUVD-2026-38545 MEDIUM
Path Traversal (CWE-22)
2026-06-16 https://github.com/denoland/deno GHSA-968w-xfqw-vp9q
5.5
CVSS 3.1 · Vendor: https://github.com/denoland/deno
Share

Severity by source

Vendor (https://github.com/denoland/deno) PRIMARY
5.5 MEDIUM
AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
vuln.today AI
5.5 MEDIUM

AV:L because the attacker must write to local node_modules; PR:L for local user or supply-chain actor; C:H for arbitrary JSON file exposure; I:N and A:N as no write or availability impact exists.

3.1 AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
4.0 AV:L/AC:L/AT:P/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

Primary rating from Vendor (https://github.com/denoland/deno).

CVSS VectorVendor: https://github.com/denoland/deno

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Local
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Jun 16, 2026 - 19:59 vuln.today
Analysis Generated
Jun 16, 2026 - 19:59 vuln.today

DescriptionCVE.org

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 narrowed to a specific directory.

The same file accessed via Deno.readTextFileSync was correctly blocked. The bug was that module resolution did not enforce the same read-permission boundary that the filesystem APIs enforced.

Proof of concept

The reporter supplied a self-contained PoC. Layout:

/tmp/deno_byonm_poc/
├── app/
│   ├── deno.json            (BYONM enabled)
│   ├── exploit.ts           (require("evil-pkg"))
│   └── node_modules/
│       └── evil-pkg/
│           └── package.json (main: "../../../secret.json")
└── secret.json              (outside --allow-read scope)

Run:

bash
deno run --no-prompt --allow-read=/tmp/deno_byonm_poc/app exploit.ts

Observed:

  • Deno.readTextFileSync("/tmp/deno_byonm_poc/secret.json") - blocked, as

expected.

  • require("evil-pkg") - returned the parsed contents of secret.json,

bypassing the read allowlist.

A control run with BYONM disabled (--no-config) blocked the require call.

Impact

The vulnerability allowed a hostile npm package installed under a BYONM node_modules to read JSON files outside the directories granted via --allow-read, up to the privileges of the OS user running Deno. In practice this exposed configuration and credential files (.env.json, cloud credentials, package lockfiles, etc.) that the user had deliberately excluded from the read scope.

The vulnerability did not grant any capability beyond what the OS user already held, did not affect runs that granted unrestricted --allow-read, and required the user to have installed and then required a hostile package, i.e. an existing supply-chain compromise. The reason it warranted a security advisory rather than a routine bug fix is that Deno's permission model promised that --allow-read=<scope> was a hard boundary *even over untrusted npm code*, and that promise was broken.

Not affected:

  • Runs without BYONM (default npm resolution went through a separate code

path that rejected the traversal).

  • Runs with full --allow-read (no boundary to bypass).
  • Non-JSON entrypoints, in practice - .js/.cjs/.mjs targets executed

rather than exposing file contents, which already implied attacker code execution within the granted permission set.

Workarounds

Users on unpatched versions could mitigate by:

  • Avoiding BYONM mode (nodeModulesDir: "manual") for projects that depended

on untrusted packages.

  • Auditing package.json main fields in node_modules for .. segments

before running.

  • Granting --allow-read only when the read scope already covered every file

the OS user could see (in which case there was no boundary to bypass and no additional exposure).

AnalysisAI

BYONM module resolution in Deno (≤ 2.7.11) allows path traversal via crafted package.json main fields, bypassing the --allow-read permission sandbox that is central to Deno's security model. A malicious npm package installed under a BYONM node_modules tree can cause require() to read and return the parsed contents of arbitrary JSON files outside the directory scope granted by --allow-read, while a direct Deno.readTextFileSync() call to the same path would be correctly blocked. No active exploitation is confirmed (not in CISA KEV), but a self-contained proof-of-concept was supplied by the reporter and is documented in the GitHub Security Advisory; real-world risk is meaningful in supply-chain scenarios where Deno's permission model is the primary isolation boundary.

Technical ContextAI

Deno is a Rust-based JavaScript and TypeScript runtime (CPE: pkg:rust/deno) that implements a fine-grained permission system, including --allow-read to restrict filesystem reads to scoped directories. BYONM mode (nodeModulesDir: "manual" in deno.json) is an opt-in configuration allowing Deno to resolve npm packages from a user-managed node_modules directory rather than Deno's default managed resolution. Under this path, the resolver reads each package's package.json, extracts the main field, and joins it to the package directory to locate the entrypoint. The root cause is CWE-22 (Path Traversal): the BYONM permission checker only verified the presence of a node_modules component in the path string and did not reject or canonicalize .. segments, so a main value of ../../../secret.json escaped the package root entirely. Because JSON entrypoints are parsed and their contents returned through require(), the traversal specifically exposed .json file contents to requiring code - a distinct exposure path from the filesystem APIs, which correctly enforced the allowlist. Non-JSON entrypoints (.js, .cjs, .mjs) caused code execution within the granted permission set rather than this data-exfiltration vector.

RemediationAI

Upgrade to Deno 2.7.12 or later, which patches the BYONM module resolver to constrain resolved entrypoint paths to the package directory and reject .. traversal; this is the vendor-confirmed fix per GHSA-968w-xfqw-vp9q at https://github.com/denoland/deno/security/advisories/GHSA-968w-xfqw-vp9q. For users who cannot immediately upgrade, three workarounds are available with distinct trade-offs: first, disable BYONM mode by removing nodeModulesDir: "manual" from deno.json and switching to Deno's default managed npm resolution, which uses a separate code path that correctly rejects path traversal - this is the most effective workaround but may require restructuring dependency management and is incompatible with projects that depend on BYONM's user-managed tree; second, manually audit all package.json files within node_modules for .. segments in the main field before executing the application, which is operationally burdensome, error-prone at scale, and must be re-performed after any dependency change; third, grant --allow-read without scope restriction only when every file the OS user can access is already acceptable to expose, which eliminates the bypass boundary entirely but surrenders the filesystem isolation that Deno's permission model is designed to provide.

CVE-2024-55591 CRITICAL POC
9.8 Jan 14

FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote

CVE-2014-7205 CRITICAL POC
10.0 Oct 08

Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t

CVE-2025-59528 CRITICAL POC
10.0 Sep 22

Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete

CVE-2017-14849 HIGH POC
7.5 Sep 28

Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc

CVE-2017-5941 CRITICAL POC
9.8 Feb 09

An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner

CVE-2014-3744 HIGH POC
7.5 Oct 23

Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi

CVE-2014-9566 HIGH POC
7.5 Mar 10

Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin

CVE-2013-4660 MEDIUM POC
6.8 Jun 28

The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic

CVE-2015-5688 MEDIUM POC
5.0 Sep 04

Directory traversal vulnerability in lib/app/index.js in Geddy before 13.0.8 for Node.js allows remote attackers to read

CVE-2026-45321 CRITICAL POC
9.6 May 12

Credential-harvesting malware compromised 84 versions of 42 TanStack npm packages on 2026-05-11 via chained GitHub Actio

CVE-2014-7192 CRITICAL POC
10.0 Dec 11

Eval injection vulnerability in index.js in the syntax-error package before 1.1.1 for Node.js 0.10.x, as used in IBM Rat

CVE-2013-4450 MEDIUM POC
5.0 Oct 21

The HTTP server in Node.js 0.10.x before 0.10.21 and 0.8.x before 0.8.26 allows remote attackers to cause a denial of se

Share

CVE-2026-49406 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy