The vulnerability exists in Deno's Node.js compatibility layer for node:tls and node:https. When a TLS connection is attempted with autoSelectFamily: true (the default), Deno tries to connect to available IP addresses for a host. If the first attempt fails (e.g., an attacker dropping packets for an IPv6 address), Deno's logic attempts to fall back and try the next address (e.g., IPv4).
This fallback mechanism involves reinitializing the underlying network socket. The vulnerability lies in this reinitialization process. The function Socket.prototype[kReinitializeHandle] in ext/node/polyfills/net.ts was responsible for this. It would copy the TLS upgrade hook (afterConnectTls) from the old, failed socket handle to the new one.
However, the afterConnectTls hook, defined in the TLSSocket constructor (ext/node/polyfills/_tls_wrap.js), was implemented as an arrow function that captured the original socket handle. Because of this, when the fallback occurred and the hook was called on the new connection, it was still operating on the context of the old, failed handle.
As a result, the startTls function was never correctly called for the new, successful TCP connection. The connection was never upgraded to TLS. The application, believing it had a secure TLS socket, would then write data (like HTTP headers with authentication tokens) to the socket, which would be transmitted in plaintext over the network.
The fix involves two parts:
- In
TLSSocket.constructor, the afterConnectTls hook was changed from an arrow function to a regular function that uses this to refer to the current handle, ensuring it always operates on the active connection.
- In
Socket.prototype[kReinitializeHandle], the logic was updated to not just copy the hook, but to also rebuild the entire promise-based state (upgrading, afterConnectTlsResolve, etc.) that tracks the TLS upgrade process. This ensures the new handle is properly configured for a fresh TLS handshake.
An attacker on the network path could deterministically trigger this vulnerability by selectively dropping connection attempts to the first IP address resolved for a dual-stack host, forcing the fallback to an address they control, and then intercepting the resulting plaintext traffic.