CVE-2026-49401: Deno Permission Bypass via Unicode Normalization Mismatch on macOS (APFS)
Summary
Deno's permission system enforces filesystem and execution restrictions by comparing the requested path against the path supplied to --deny-read, --deny-write, --deny-run, or --deny-ffi. On macOS, that comparison was done at the raw-byte level while the APFS filesystem treats different Unicode spellings of the same name as the same file.
That means a program could reach a denied path by spelling it differently than the deny rule. For example, with --deny-read=/secrets/passwörter.txt, a script could still read the file by opening /secrets/passwo\u0308rter.txt (NFD instead of NFC), or /SECRETS/PASSWÖRTER.txt (different case, since default APFS volumes are case-insensitive). Other forms include ligature characters (fi vs fi, ff vs ff, …) and German ß vs ss.
The denied path and the requested path differed at the byte level, so Deno's permission check passed; the kernel then resolved them to the same inode and served the file anyway. The same flaw affected --deny-write, --deny-run, and --deny-ffi, which share the same path-comparison code.
Am I affected?
You are potentially affected if all of the following are true:
1. You run Deno on macOS (the issue is specific to APFS path-equivalence rules; Linux and Windows are not affected by this variant). 2. You rely on --deny-read, --deny-write, --deny-run, or --deny-ffi as a security boundary against less-trusted code — a dependency, plugin, or attacker-controlled input. 3. The protected path contains characters that have alternate Unicode spellings — most commonly accented characters (é, ñ, ö, …), German ß, or Latin ligatures — or you rely on case-sensitivity on a default APFS volume.
If you only run fully trusted code, or your deny rules cover paths that are pure ASCII with no case-sensitive aliases, you are not exposed to this specific bypass.
Impact
A program running with broad --allow-read (or --allow-write / --allow-run / --allow-ffi) but with --deny- carve-outs for specific paths could read, write, execute, or load via FFI those denied paths by referring to them through a Unicode- or case-equivalent spelling. The sandbox model on macOS was weaker than the flags suggested.
Workaround
If you cannot upgrade immediately:
- Prefer --allow- allowlists over --deny- denylists. Allow rules match against the original specifier, so an attacker-supplied alternate spelling will not match a path you didn't explicitly grant. - Do not rely on case-sensitivity of paths on macOS for security boundaries; default APFS volumes are case-insensitive.
Fix
On macOS, Deno now normalizes both the deny-rule path and the requested path to NFC and applies Unicode case folding before comparing them. This matches how APFS resolves paths at the inode level, so byte-different but equivalent spellings are now rejected by the same deny rule.
Other sources
Deno is a JavaScript, TypeScript, and WebAssembly runtime. Prior to 2.7.14, Deno's permission system enforces filesystem and execution restrictions by comparing the requested path against the path supplied to --deny-read, --deny-write, --deny-run, or --deny-ffi. On macOS, that comparison was done at the raw-byte level while the APFS filesystem treats different Unicode spellings of the same name as the same file. That means a program could reach a denied path by spelling it differently than the deny rule. This vulnerability is fixed in 2.7.14.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
rust/denoto a version that resolves this vulnerability.Fixed in 2.7.14 - Upgrade
Upgrade
denoto a version that resolves this vulnerability.Fixed in 2.7.14 - Configuration
Ensure Deno is configured to use macOS APFS-safe path comparison by normalizing both the --deny-* rule path and the requested path to NFC and applying Unicode case folding before comparing them (this is what fixes the Deno Permission Bypass via Unicode Normalization Mismatch on macOS/APFS).
Deno permission system on macOS (APFS) Deno Unicode normalization for deny-rule path comparison = NFC (and apply Unicode case folding before comparing requested vs --deny-* paths) - Compensating control
If you cannot upgrade immediately, rely on fully trusted code only, and ensure your --deny-* carve-outs cover paths used as security boundaries for less-trusted code (the bypass affects cases where broad --allow-* permissions are combined with --deny-* rules on macOS).
Event History
Frequently Asked Questions
What is the severity of CVE-2026-49401?
The severity of CVE-2026-49401 is classified as medium with a score of 5.2.
How does CVE-2026-49401 affect the Deno permission system?
CVE-2026-49401 affects the Deno permission system by allowing unintended access due to path comparison issues in macOS.
What impact does CVE-2026-49401 have on filesystem security?
CVE-2026-49401 can potentially compromise filesystem security by allowing unauthorized read, write, or execute operations.
Is CVE-2026-49401 related to any specific operating system?
Yes, CVE-2026-49401 is specifically related to the macOS operating system.
What is the recommended mitigation for CVE-2026-49401?
The recommended mitigation for CVE-2026-49401 is to ensure that the appropriate path-denying flags are consistently used when executing Deno commands.