high · 7.5Jun 26, 2026

Hysteria Server Crash via Tiny QUIC max_datagram_frame_size

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

An authenticated Hysteria client can crash the server instantly by advertising a tiny QUIC datagram size and then sending a UDP packet, triggering a slice-bounds panic in the fragmentation code.

Packagegithub.com/apernet/hysteria
Ecosystemgo
Affected< 2.9.2
Fixed in2.9.2

The problem

Hysteria versions before 2.9.2 crash when a client advertises a very small QUIC max_datagram_frame_size (for example, 20 bytes) and then triggers a UDP response from the server.

When sendMessageAutoFrag catches a DatagramTooLargeError from quic-go, it calls FragUDPMessage with the attacker-supplied max payload size. The function blindly computes maxPayloadSize := maxSize - m.HeaderSize(). If maxSize is smaller than the header, the result is zero or negative.

The subsequent slice operation frag.Data = fullPayload[off : off+payloadSize] panics, terminating the entire server process.

Any authenticated client can trigger this. No special privileges are needed beyond a valid credential.

Proof of concept

A working proof-of-concept for this issue in github.com/apernet/hysteria, with the exact payload below.

bash
# 1. Run a local UDP echo target
go run -tags poc ./poc_udp_frag_panic.go \
  --server 127.0.0.1:8443 \
  --auth udp-frag-panic-poc \
  --insecure \
  --target 127.0.0.1:19090 \
  --max-datagram 20

# The client connects via HTTP/3, authenticates normally, then sends
# a single Hysteria UDP datagram addressed to the echo target.
# The QUIC connection advertises MaxDatagramFrameSize=20, which is
# smaller than the Hysteria UDP message header (~30 bytes for a short addr).
# The server tries to fragment the reply, computes a negative payload size,
# and panics with: runtime error: slice bounds out of range.

The root cause (CWE-1325, effectively CWE-400) is a missing bounds check in core/internal/frag/frag.go. Before the fix, FragUDPMessage assumed maxSize > m.HeaderSize() without verifying it. The attacker fully controls MaxDatagramFrameSize via the QUIC transport parameter negotiation, and quic-go faithfully surfaces that value in DatagramTooLargeError.MaxDatagramPayloadSize.

The patch adds an early return in FragUDPMessage when maxSize <= m.HeaderSize(), preventing the negative slice index from ever being computed. This also causes sendMessageAutoFrag to drop the packet rather than crash.

The fix

Upgrade to Hysteria 2.9.2 or later. The release is tagged app/v2.9.2 and is described by the maintainers as containing important security fixes. No configuration-level workaround exists for earlier versions; the only safe remediation is to upgrade.

Reporter not attributed.

References: [1][2]

Related research