The one fix that matters in Deno 2.9.8: it stops trusting the compromised eMudhra root

This patch release has 13 fixes, half of them permission and sandbox edges, half Node-compatibility semantics. The eMudhra distrust lines up with what uv and CPython did the same week.

Deno 2.9.8 shipped on October 21 with 13 fixes. Patch releases rarely deserve a post, but two items here do: it stops trusting the compromised eMudhra certificate authority, and deno compile now checks read permission for dynamically imported local files.

The 13 fixes, sorted by nature

Area Items
Security distrust eMudhra CA; bump rand to a patched version
Permission / sandbox deno compile checks read permission for dynamic local imports; keep op contexts alive until the isolate is disposed
Node compatibility X.509v1 handling aligned with OpenSSL; mock.reset() restores mock.method(); assert accepts message functions and format arguments
NAPI bounds check for napi_create_dataview overflow; ignore callback return value while an exception is pending
Tooling zsh completion for script paths in bare deno run; coverage skips the V8 code cache; npm package link name validation
Runtime hyper and hyper-util bumped so the idle interval is cancelled when the pool empties

The v2.9.8 release page

eMudhra is an Indian CA. Once it is compromised, every client has exactly one job: delete it from the trust store. Deleting is easy; deleting completely is not:

  • the operating system has its own root store;
  • runtimes (Node, Deno, Go, Python’s certifi) often ship their own copy;
  • interpreters managed by language tooling (say, a uv-managed CPython) carry yet another copy;
  • each copy updates on a different schedule.

That is why you see the same fix land in several projects within days: Deno 2.9.8 removes it, uv 0.13.4/0.13.5 removes it and also bumps its managed CPython builds to versions carrying certifi 2026.10.19. That is not duplicated work; every trust store has to be edited by hand.

The tls item sits mid-list in the release notes and is easy to skip

The practical consequence: if your service talks to a site whose certificate is still issued under eMudhra, handshakes start failing after the upgrade. That is expected behavior. The fix is for the other side to reissue, not for you to add a trust exception.

The compile permission fix: does a compiled binary inherit permissions?

deno compile produces a single-file executable. The subtle bug: dynamically importing a local file did not check read permission.

// a path assembled at runtime — after compile it still reads that file
const mod = await import(new URL('./plugins/' + name + '.ts', import.meta.url).href);

Static import paths are known at bundle time; dynamic ones are not. If the permission model only covers the former, --allow-read is decoration: assemble any path and read any file.

The general lesson is worth keeping: wherever “known at build time” meets “decided at runtime”, permission checks leak. The same shape shows up in Node’s realpathSync fix — the path was checked, but not after symlink resolution.

Deno’s permission docs: read access is granted as a path allowlist

Three Node-compatibility fixes

ext/node reimplements Node’s built-ins the Deno way, so its bug tracker always carries one class of report: “Node does it this way, Deno doesn’t.”

  • X.509v1 handling aligned with OpenSSL: v1 certificates have no extension fields, and implementations historically differ. Handshake differences surface as “some sites do not connect from Deno”.
  • mock.reset() restores mock.method(): in tests, reset means “clear call records”, not “dismantle the mock”. Without restoring the implementation, a spy becomes an empty function and every later assertion is wrong.
  • assert accepts message functions and format arguments: pure alignment, but with wide impact — plenty of test suites write assert.equal(a, b, () => 'context').

My take

Deno’s positioning is clear: Node compatibility plus secure by default, so its patch releases are always half security and half compatibility. 2.9.8 adds no features, but if you run a TLS client, the eMudhra item is worth upgrading today.

One observation: in a single week, eMudhra appeared in the release notes of Deno, uv and CPython — one CA incident forces every piece of software that ships its own root store to cut a release. Which means any design that bundles a trust store must be able to ship frequently, or a single incident will drag on for months.

The Deno blog — patch releases rarely get a post, the detail lives in the Release

← Back to all posts

Comments

…