high · 7.5 Patched

pyasn1 has quadratic-complexity denial of service in binary REAL decoding

CVE-2026-119197 · GHSA-mm57-4v3p-rchx · published 30 Oct 2026

How serious is it

  • Severity: high, CVSS score 7.5 out of 10.
  • No exploit prediction (EPSS) score yet.
  • Not on the CISA list of exploited vulnerabilities.
  • No public exploit in Exploit-DB.

Is your app affected by CVE-2026-119197?

Paste this prompt into Claude Code, Cursor or any AI coding tool: it runs a free Shippable scan of your project and fixes what it finds. Built with Lovable, Bolt or v0? Scan your live app. Or upload your package file.

Who is affected

  • pyasn1 (PyPI) <= 0.6.4

How to check

  1. Run pip show pyasn1 in your project to see the installed version, including copies pulled in by other packages.
  2. Or paste your lockfile into the checker: it lists every package with a known vulnerability, this one included.
  3. Or run npx shippable-dev scan localhost:3000 in your project folder. It reads your lockfile and flags this vulnerability along with every other known one.

How to fix

Copies a prompt for Claude Code, Cursor or Codex: it checks your lockfiles for this and upgrades it.
  1. Upgrade pyasn1 to 0.6.5 or later, commit the lockfile and redeploy.
  2. If a vulnerable version was live, check your logs and rotate the secrets that server could read.

The advisory

## Summary In pyasn1 0.6.4 and earlier, decoding a binary-encoded ASN.1 REAL with a large mantissa can consume CPU time quadratic in the mantissa length. The BER, CER, and DER decoders all use the affected `RealPayloadDecoder`. An application is exposed when it passes attacker-controlled ASN.1 containing a REAL value to one of these decoders, either without an `asn1Spec` or with a schema that includes REAL. The work occurs inside `decode()`; the application does not need to convert, print, or otherwise use the resulting REAL object. This is distinct from [CVE-2026-59886](https://github.com/advisories/GHSA-hm4w-wwcw-mr6r), which concerns converting an already-decoded REAL to a Python float. That issue was fixed in 0.6.4 and its advisory states that decoding alone does not trigger it. ## Root cause and affected components For binary REAL values, [`RealPayloadDecoder.valueDecoder` in v0.6.4](https://github.com/pyasn1/pyasn1/blob/v0.6.4/pyasn1/codec/ber/decoder.py#L535-L603) builds the mantissa one octet at a time: ```python p = 0 while chunk: p <<= 8 p |= chunk[0] chunk = chunk[1:] ``` Each shift processes an integer that grows with the mantissa; with byte strings, each slice also copies the remaining suffix. Repeating both operations for every octet makes decoding quadratic in mantissa size. The decoder's [eight-octet length-field limit](https://github.com/pyasn1/pyasn1/blob/v0.6.4/pyasn1/codec/ber/decoder.py#L1704-L1717) does not impose a practical mantissa-size limit for the inputs demonstrated below. [CER](https://github.com/pyasn1/pyasn1/blob/v0.6.4/pyasn1/codec/cer/decoder.py#L51-L62) and [DER](https://github.com/pyasn1/pyasn1/blob/v0.6.4/pyasn1/codec/der/decoder.py#L23-L31) reuse the BER REAL payload decoder, so all three paths reach this loop. The vulnerable loop is present in every available repository release tag inspected, from v0.2.1 through v0.6.4. Runtime measurements below were made on v0.6.4; older releases were checked for the loop, not benchmarked individually. ## Impact A comparatively small REAL value can hold a decoder worker on one CPU core for seconds or longer. The attacker must be able to supply data that the application sends to an affected decoder, and application-level input limits may reduce exposure. The demonstrated effect is CPU exhaustion during decoding; this advisory does not assert a network endpoint, unauthenticated access, or an affected downstream application by itself. ## Reproduction and evidence The following example uses pyasn1 0.6.4. The `0x09` tag identifies REAL; `0x80 0x00` selects a positive, base-2 binary value with a one-octet zero exponent, followed by a large mantissa. It exercises `decode()` only. ```python import time from pyasn1.codec.ber import decoder as ber from pyasn1.codec.cer import decoder as cer from pyasn1.codec.der import decoder as der def real_value(mantissa_octets): content = b"\x80\x00" + b"\xff" * mantissa_octets length = len(content).to_bytes(3, "big") return b"\x09\x83" + length + content for codec in (ber, cer, der): for size in (50_000, 100_000, 200_000): substrate = real_value(size) started = time.process_time() value, rest = codec.decode(substrate) print(codec.__name__, size, time.process_time() - started) assert not rest assert tuple(value)[1:] == (2, 0) ``` The original report measured the following BER CPU times on repository commit `aa05757`. That commit is later than the official v0.6.4 tag; the vulnerable loop is identical in the tagged release. | Mantissa size | Reporter's BER CPU time | | ---: | ---: | | 50,000 octets | 0.328 s | | 100,000 octets | 1.299 s | | 200,000 octets | 6.043 s | | 400,000 octets | 24.095 s | The same report measured 5.645 s for a 200,000-octet mantissa through DER. A separate local reproduction on the official v0.6.4 tag (`d43496f`, CPython 3.14.8, macOS arm64) measured BER at 0.209 s, 0.884 s, and 3.451 s for 50,000, 100,000, and 200,000 mantissa octets respectively. CER and DER each took about 0.89 s at 100,000 octets. These are machine-specific measurements; the repeated near-fourfold cost for doubled input is the relevant result. Neither reproduction calls `float()`, `str()`, or `prettyPrint()`. ## Fix pyasn1 0.6.5 replaces the per-octet shift and slice loop with one `int.from_bytes(bytes(chunk), "big")` conversion. Sign, scale, exponent, and the decoded REAL tuple are preserved. The fix is in the shared BER payload decoder and therefore covers BER, CER, and DER. A local check of the 0.6.5 candidate decoded a 200,000-octet mantissa correctly through all three codecs; the check does not establish behavior for every application using REAL. ## Workarounds Upgrade to pyasn1 0.6.5. Until then, reject or strictly limit attacker-controlled ASN.1 input that may contain REAL values before passing it to pyasn1. The appropriate size limit depends on the application's available CPU time and request volume.

Check your whole app

Dependencies are only half of it. Free and read-only: before you push, run npx shippable-dev scan localhost:3000 in your project folder, no account needed. For your live app, you prove it's yours with a one-line tag first.

References

Merged from GitHub Advisory Database, OSV. Last updated 31 Oct 2026. All vulnerabilities · RSS · JSON