Scapy

MEDIUM CVSS 5.3 · GHSA-456h-w4v7-hvpr ↗

BER Decoder Mutual Recursion Has No Depth Limit, 250 Nested SEQUENCEs Crash the Process

scapy (pip)
scapy/asn1/ber.py
CWE-674
5.3 MEDIUM
< 2.8.0
2.8.0
2026-09-08
None
infycore
Patched

Scapy’s ASN.1/BER decoder implements a mutually recursive call structure between BERcodec_SEQUENCE.do_dec() and BERcodec_Object.dec(). Neither function enforces a nesting depth limit. A crafted packet containing 250 nested SEQUENCE structures (833 bytes) exhausts Python’s call stack and raises an unhandled RecursionError. Any service that parses untrusted BER-encoded network traffic via Scapy is affected. No authentication is required; the attacker sends a single packet.

01 Root Cause

The decoder in scapy/asn1/ber.py uses mutual recursion: BERcodec_SEQUENCE.do_dec() iterates over the contents of a SEQUENCE and calls BERcodec_Object.dec() for each child element; dec() dispatches to the type-appropriate codec, which for a nested SEQUENCE calls do_dec() again. This creates one Python stack frame per nesting level. The safe=True parameter catches exceptions from malformed encodings but does not bound recursion depth; a structurally valid but deeply nested input bypasses it entirely.

# scapy/asn1/ber.py (simplified) -- recursive path with no depth guard class BERcodec_SEQUENCE(BERcodec_Object): @classmethod def do_dec(cls, s, context=None, safe=False): ... while s: obj, s = BERcodec_Object.dec(s, context, safe) # recurses for nested SEQUENCEs ...
02 Reproduction

The advisory demonstrates the crash threshold with 250-level nesting. At 250 levels the decoder generates 3,995 stack frames before Python raises RecursionError: maximum recursion depth exceeded. The table below shows nesting depth vs. encoded size and outcome:

Depth Bytes Result 50 102 OK 100 239 OK 250 833 CRASH (RecursionError, 3,995 frames) 500 1833 CRASH

The attacker constructs a BER-encoded stream of 250 nested empty SEQUENCE tags. The payload is 833 bytes. No special protocol state or credentials are required; the crash occurs on receipt and decode attempt of the first such packet.

03 Impact

The crash denies service to any Scapy-based process that parses untrusted network traffic. Affected protocol parsers include TLS certificate and handshake parsing, SNMP packet decoding, X.509 certificate parsing, and LDAP packet handling — all of which use the BER decoder. Intrusion detection systems, traffic analyzers, and security appliances built on Scapy are particularly exposed.

The attack is persistent and repeatable: an attacker can resend the 833-byte packet after each process restart to maintain a persistent denial of service. No authentication or prior session state is needed.

04 CVSS Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L Base Score: 5.3 MEDIUM AV:N: attacker sends a crafted packet over the network AC:L: no special conditions; 250-level SEQUENCE nesting in 833 bytes PR:N: no authentication required UI:N: no user interaction needed S:U: scope unchanged; crash contained to the Scapy process C:N: no data is disclosed I:N: no data is modified A:L: process crashes; attacker can repeat indefinitely after restart
05 Recommended Fix

Upgrade to scapy ≥ 2.8.0, which introduces a configurable nesting depth limit in the BER decoder. The fix enforces a maximum depth and raises BER_Decoding_Error when exceeded, rather than allowing unbounded recursion.

pip install "scapy>=2.8.0"

Patched in scapy 2.8.0. Advisory: GHSA-456h-w4v7-hvpr ↗.