CVE-2026-49401
Deno Permission Bypass via Unicode Normalization Mismatch on macOS (APFS)
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.
Attack profile
How easy it is to exploit
- Attack vector
- Local
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.3
Deno Permission Bypass via Unicode Normalization Mismatch on macOS (APFS)
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.
- Record
CVE-2026-49401- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:N - Weakness
- CWE-41, CWE-176
- Updated
- 2026-11-02
EUVDEUVD-2026-38547
7.3
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.
- Record
EUVD-2026-38547- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-8xpq-cjcf-3wh9
7.3
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:
- You run Deno on macOS (the issue is specific to APFS path-equivalence rules; Linux and Windows are not affected by this variant).
- You rely on
--deny-read,--deny-write,--deny-run, or--deny-ffias a security boundary against less-trusted code — a dependency, plugin, or attacker-controlled input. - 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.
- Record
GHSA-8xpq-cjcf-3wh9- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:N - Weakness
- CWE-41, CWE-176
- Updated
- 2026-11-02
NVD
7.3
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.
- Record
CVE-2026-49401- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:N - CVSS 3.1
- 8.4 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N - Weakness
- CWE-41, CWE-176
- Updated
- 2026-11-02
OSV
7.3
Deno Permission Bypass via Unicode Normalization Mismatch on macOS (APFS)
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.
- Record
CVE-2026-49401- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:N - Weakness
- CWE-176, CWE-41
- Updated
- 2026-11-02
OSVGHSA-8xpq-cjcf-3wh9
7.3
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:
- You run Deno on macOS (the issue is specific to APFS path-equivalence rules; Linux and Windows are not affected by this variant).
- You rely on
--deny-read,--deny-write,--deny-run, or--deny-ffias a security boundary against less-trusted code — a dependency, plugin, or attacker-controlled input. - 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.
- Record
GHSA-8xpq-cjcf-3wh9- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:N - Weakness
- CWE-176, CWE-41
- Updated
- 2026-11-02
OSVJLSEC-2026-655
8.4
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:
- You run Deno on macOS (the issue is specific to APFS path-equivalence rules; Linux and Windows are not affected by this variant).
- You rely on
--deny-read,--deny-write,--deny-run, or--deny-ffias a security boundary against less-trusted code — a dependency, plugin, or attacker-controlled input. - 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.
- Record
JLSEC-2026-655- CVSS 3.1
- 8.4 High
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N - Updated
- 2026-11-02
Affected products
Affected packages
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-49401 is a high vulnerability (CVSS 7.3) in Deno, published June 16, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.20%, the 9th percentile. Fixed in deno 2.7.14.