CVE-2026-49401Medium· 5.2▾ SunlitDeno: Permission Bypass via Unicode Normalization Mismatch on macOS (APFS)
▾ Sunlit zone — Low / medium · no exploitation signal
impact 28.6 · likelihood 0 · exploitation 0
Need a working PoC? Pro members can cast a request and our team develops one — it lands right here.
Exploit-prediction probability, daily snapshots since Jul 4.
Disclosure to exploitation, from the record and what we observed since indexing it.
Disclosed via GHSA
0.1%
0.1% → 0.2%
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.
You are potentially affected if all of the following are true:
--deny-read, --deny-write, --deny-run, or --deny-ffi
as a security boundary against less-trusted code — a dependency, plugin,
or attacker-controlled input.é, ñ, ö, …), 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.
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.
If you cannot upgrade immediately:
--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.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.
deno <= 2.7.13Upgrade to a patched release:
deno 2.7.14Connected by shared product, vendor, weakness, or advisory.
CVE-2026-44726High· 7.4Deno's TLS retry copies stale upgrade hook, risking plaintext traffic
CVE-2021-32619Critical· 9.8Deno's static imports inside dynamically imported modules do not adhere to permission checks
CVE-2026-49859Medium· 5.2Deno: `fetch()` API sandbox bypass via missing DNS resolution check
CVE-2026-49860Medium· 5.2Deno: WebSocket API sandbox bypass via missing post-DNS check
CVE-2026-49402High· 8.1Deno: Command Injection via spawnSync & spawn on Windows
CVE-2026-49440High· 7.4Deno: Miller-Rabin Primality Test Allows Zero Rounds