Skip to content

ssl: distrust compromised eMudhra intermediate CA keys #160040

Open

Description

@tiran

Feature or enhancement

I propose to add a small denylist to _ssl that rejects any TLS certificate chain containing one of the recently compromised eMudhra intermediate CA keys. The check runs during certificate verification and matches the DER-encoded SubjectPublicKeyInfo, so cross-signed certs that reuse a key are blocked, too.

Yesterday a set of eMudhra intermediate keys were disclosed as compromised and revoked, see https://emudhra.we-have-a-problem.com/. d=4 isn't a secure EC private key. Removing trust is the root store's job, but the update lags in practice, and there is no reliable way to propagate an intermediate revocation to applications. Until the roots are gone, Python still completes handshakes through a known-bad key.

As a defense in depth Python should blocks those connections in the meantime. With a simple callback, this can be enforced on every SSLContext when verification is enabled (CERT_OPTIONAL / CERT_REQUIRED); CERT_NONE is unaffected.

Has this already been discussed elsewhere?

No response given

Links to previous discussion of this feature:

Golang has implemented filtering to address CVE-2026-111943.

Linked PRs

Activity

  1. added 2 commits that reference this issue on Oct 21, 2026
  2. tiran commented on Oct 21, 2026

    @tiran
    MemberAuthor
  3. added a commit that references this issue on Oct 21, 2026
  4. added a commit that references this issue on Oct 21, 2026
  5. zooba commented on Oct 21, 2026

    @zooba
    Member

    I don't see why we should assume that users can update their entire application runtime faster than their OS certificates.

    Certificate bundles are intended to be updated efficiently and without breaking unrelated parts of the applications relying on them. Updating a Python release is nowhere near as safe.

  6. added a commit that references this issue on Oct 21, 2026
  7. sethmlarson commented on Oct 21, 2026

    @sethmlarson
    Contributor

    Thanks for suggesting this and submitting a patch @tiran. My biggest concern is the precedence that this sets, would we reach for this functionality for future compromises and tell users to upgrade their Python? I know you're putting this forward as defense-in-depth so it's not either-or, but I am cautious about signing us up for more expedited releases and asking users to mitigate by updating the Python runtime.

    My preference is providing users and distributions mechanisms to resolve these issues themselves without requiring a series of expedited Python releases and upgrades. Maybe this would take the form of a defined pattern for integrating a CRL for Python distributions? (upki?) And maybe leaning more on Windows and macOS certificate APIs?

  8. tiran commented on Oct 21, 2026

    @tiran
    MemberAuthor

    The situation would be far less messy if packages would stop shipping their own trust store and solely rely on system trust store. Then users would only need to update or reconfigure their OS and everything would be fine. I'm looking forward to a world where every Linux OS has something like upki or a PKCS#11 provider with OS-wide revocation lists and policies.

    It's 2026 and certifi is still a thing... On top of that, packages like pip also vendor certifi. And that's just the tip of the ice berg! I know of at least one more packages with almost 14 million downloads per day that ships a custom root CA bundle with eMudhra certs (the maintainers are aware). Let's not forget about packages with upper version caps that prevent security updates.

    I don't have to explain to you how serious a compromise root or intermediate CA is. Thankfully it does not happen that often. The last major compromises happened in 2011. DigiNotar got owned and TurkTrust accidently issued two CAs. I strongly believe that this event requires special care and defense-in-depth. Google felt the same way.

  9. tiran commented on Oct 21, 2026

    @tiran
    MemberAuthor

    Sorry, I forgot to address your biggest concern:

    My biggest concern is the precedence that this sets, would we reach for this functionality for future compromises and tell users to upgrade their Python?

    I agree, it's a valid concern. Let's document when and why Python is blocking certificates:

    • Python will only add new certificates to the block list when a globally trusted root CA or intermediate CA for TLS server authentication is compromised and MitM attacks are possible.
    • The block list is designed as last line of defense. Users and package maintainers should update their code.
  10. 23 remaining items

  11. added a commit that references this issue on Oct 24, 2026
  12. moved this from Todo to In Progress in Release and Deferred blockers 🚫on Oct 24, 2026
  13. tiran commented on Oct 24, 2026

    @tiran
    MemberAuthor

    @sethmlarson @gpshead @Yhg1s @hugovk You may have to release security updates of Python 3.13-3.15 with my fix ASAP.

    Please take a look at @JSGette comment on DataDog/datadog-agent#58679

    Confirmed on the signed 7.84.5 Windows MSI (ZD-3042491, incident_62343): ssl.create_default_context() still accepts the AAA cross-signed eMudhra chains, because Python loads the Windows CA and ROOT stores and never reads Disallowed. On Windows, datadog_checks_base HTTP integrations without tls_ca_cert call load_default_certs() and inherit the same trust.

    It looks like Windows still ships the Sectigo / Comodo AAA Certificate Service in Windows' trust store. ssl.create_default_context() loads the trust anchor. I do not have access to a Windows machine at the moment. Can somebody test and confirm the issue?

  14. hugovk commented on Oct 24, 2026

    @hugovk
    Member

    @tiran I've added you to the bypass list so you can open more PRs.

  15. added 4 commits that reference this issue on Oct 24, 2026
  16. added 4 commits that reference this issue on Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions