Crypto-View

certbot/certbot

Readiness score
0 of 100
How this is calculated · previous scan 0
Cryptographic posture
Quantum-vulnerable 164 Already broken 36 Reduced margin 7 Quantum-safe 2
To address166
Key establishment68
Inventory only4
Total findings213
What was analysed
Branch main
Commit 485649333422392901e7ef891630f0129985df8e hooks: truncate the correct env var (#10779)
Committed 2026-09-09 20:35 UTC
Scanned 2026-09-09 23:57 UTC 1 day ago
Coverage 784 files, 359 python

Earlier scans of this repository

13 scans · score 0 → 0 · compare any two
13 scans · 0 → 0 (unchanged). The filled point is the scan you are reading.
Scanned Commit Score To address
4 hours ago 485649333422 main 0 180 Compare
5 hours ago 485649333422 main 0 168 Compare
19 hours ago e75e7378cd02 0 168 Compare
21 hours ago 485649333422 main 0 166 Compare
1 day ago 485649333422 main 0 166 Compare
1 day ago 485649333422 main 0 166 Compare
1 day ago 485649333422 main 0 166 Compare
1 day ago this scan 485649333422 main 0 166
3 days ago 56ee04928d67 main 0 165 Compare
3 days ago 56ee04928d67 main 0 165 Compare
4 days ago 56ee04928d67 main 0 165 Compare
10 days ago 2b817be14620 main 0 165 Compare
11 days ago e75e7378cd02 0 165 Compare

Every repository in this history is re-scanned weekly.

List of cryptographic assets

RSA-1024512-bit Already broken 19 places See details

X.509 certificate

A PEM certificate. The subject public-key algorithm and key size are read from the SubjectPublicKeyInfo structure, and the not-after date is reported so certificates that outlive the migration window are visible.

This is a digital identity document. Its expiry date matters: one valid for many years locks in today's algorithms for that long.

What to do. Shorten certificate lifetimes so re-issuing with a post-quantum key is routine.

  1. acme/src/acme/_internal/tests/testdata/cert-100sans.pem:1 test path -----BEGIN CERTIFICATE-----
  2. acme/src/acme/_internal/tests/testdata/cert-idnsans.pem:1 test path -----BEGIN CERTIFICATE-----
  3. acme/src/acme/_internal/tests/testdata/cert-san.pem:1 test path -----BEGIN CERTIFICATE-----
  4. acme/src/acme/_internal/tests/testdata/cert.pem:1 test path -----BEGIN CERTIFICATE-----
  5. acme/src/acme/_internal/tests/testdata/csr-100sans.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  6. acme/src/acme/_internal/tests/testdata/csr-6sans.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  7. acme/src/acme/_internal/tests/testdata/csr-idnsans.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  8. acme/src/acme/_internal/tests/testdata/csr-nosans.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  9. acme/src/acme/_internal/tests/testdata/csr-san.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  10. acme/src/acme/_internal/tests/testdata/csr.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  11. certbot/src/certbot/tests/testdata/cert-5sans_512.pem:1 test path -----BEGIN CERTIFICATE-----
  12. certbot/src/certbot/tests/testdata/cert-san_512.pem:1 test path -----BEGIN CERTIFICATE-----
  13. certbot/src/certbot/tests/testdata/cert_512.pem:1 test path -----BEGIN CERTIFICATE-----
  14. certbot/src/certbot/tests/testdata/cert_512_bad.pem:1 test path -----BEGIN CERTIFICATE-----
  15. certbot/src/certbot/tests/testdata/csr-6sans_512.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  16. certbot/src/certbot/tests/testdata/csr-nonames_512.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  17. certbot/src/certbot/tests/testdata/csr-nosans_512.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  18. certbot/src/certbot/tests/testdata/csr-san_512.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  19. certbot/src/certbot/tests/testdata/csr_512.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
pem.certificate
RC4 Already broken 8 places See details

TLS cipher suites pinned in configuration

An `ssl_ciphers`, `SSLCipherSuite` or `ssl-default-bind-ciphers` directive. Every suite available today uses a classical key exchange; a suite naming RC4, DES, 3DES, EXPORT or NULL is broken now.

This is already unsafe today, with no quantum computer involved. RC4 keystream biases break it classically; it is prohibited in TLS by RFC 7465.

What to do. Remove anything below TLS 1.2. The key exchange changes when the server software offers a hybrid group, not before.

  1. certbot-ci/src/certbot_integration_tests/assets/sample-config/options-ssl-apache.conf:7 test path SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-
  2. certbot-compatibility-test/nginx/nginx-roundtrip-testdata/guide-to-nginx-ssl-spdy-hsts/nginx.conf:104 test path ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA2
  3. certbot-compatibility-test/nginx/nginx-roundtrip-testdata/iredmail/iredadmin.conf:10 test path ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
  4. certbot-compatibility-test/nginx/nginx-roundtrip-testdata/iredmail/nginx.conf:41 test path ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
  5. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/passing/ipv6-1143b.conf:14 test path SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH +aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
  6. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/passing/ipv6-1143d.conf:14 test path SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH +aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
  7. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/passing/two-blocks-one-line-1693.conf:13 test path SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EEC DH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRS A RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"
  8. certbot/src/certbot/_internal/tests/plugins/apache/testdata/gentoo_apache/apache/apache2/vhosts.d/00_default_ssl_vhost.conf:34 test path SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SH
config.tls-ciphers · CWE-757
MD5 Already broken 6 places See details

TLS cipher suites pinned in configuration

An `ssl_ciphers`, `SSLCipherSuite` or `ssl-default-bind-ciphers` directive. Every suite available today uses a classical key exchange; a suite naming RC4, DES, 3DES, EXPORT or NULL is broken now.

This is already unsafe today, with no quantum computer involved. Practical chosen-prefix collisions exist; MD5 has no remaining security as a digest.

What to do. Remove anything below TLS 1.2. The key exchange changes when the server software offers a hybrid group, not before.

config.tls-ciphers · CWE-757
MD5 Already broken 2 places See details

Broken hash function

`hashlib.md5()` or `hashlib.sha1()`. Both have practical collisions. Where the call is annotated `usedforsecurity=False` the finding is recorded as inventory instead.

This is already unsafe today, with no quantum computer involved. Practical chosen-prefix collisions exist; MD5 has no remaining security as a digest.

What to do. SHA-256, or SHA-384 for long-lived signatures.

  1. certbot/src/certbot/_internal/account.py:70 hasher = hashlib.md5()
  2. certbot/src/certbot/_internal/account.py:75 hasher = hashlib.new('md5', **cast(Mapping[str, Any], {"usedforsecurity": False}))
py.hashlib.weak · CWE-328
RSA-10241024-bit Already broken 1 place See details

X.509 certificate

A PEM certificate. The subject public-key algorithm and key size are read from the SubjectPublicKeyInfo structure, and the not-after date is reported so certificates that outlive the migration window are visible.

This is a digital identity document. Its expiry date matters: one valid for many years locks in today's algorithms for that long.

What to do. Shorten certificate lifetimes so re-issuing with a post-quantum key is routine.

  1. acme/src/acme/_internal/tests/testdata/rsa1024_cert.pem:1 test path -----BEGIN CERTIFICATE-----
pem.certificate
RSA2048-bit Quantum-vulnerable 36 places See details

X.509 certificate

A PEM certificate. The subject public-key algorithm and key size are read from the SubjectPublicKeyInfo structure, and the not-after date is reported so certificates that outlive the migration window are visible.

This is a digital identity document. Its expiry date matters: one valid for many years locks in today's algorithms for that long.

What to do. Shorten certificate lifetimes so re-issuing with a post-quantum key is routine.

  1. acme/src/acme/_internal/tests/testdata/cert-ipsans.pem:1 test path -----BEGIN CERTIFICATE-----
  2. acme/src/acme/_internal/tests/testdata/cert-ipv6sans.pem:1 test path -----BEGIN CERTIFICATE-----
  3. acme/src/acme/_internal/tests/testdata/critical-san.pem:1 test path -----BEGIN CERTIFICATE-----
  4. acme/src/acme/_internal/tests/testdata/csr-ipsans.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  5. acme/src/acme/_internal/tests/testdata/csr-ipv6sans.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  6. acme/src/acme/_internal/tests/testdata/csr-mixed.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  7. acme/src/acme/_internal/tests/testdata/rsa2048_cert.pem:1 test path -----BEGIN CERTIFICATE-----
  8. certbot-ci/src/certbot_integration_tests/assets/sample-config/archive/a.encryption-example.com/cert1.pem:1 test path -----BEGIN CERTIFICATE-----
  9. certbot-ci/src/certbot_integration_tests/assets/sample-config/archive/a.encryption-example.com/chain1.pem:1 test path -----BEGIN CERTIFICATE-----
  10. certbot-ci/src/certbot_integration_tests/assets/sample-config/archive/a.encryption-example.com/fullchain1.pem:1 test path -----BEGIN CERTIFICATE-----
  11. certbot-ci/src/certbot_integration_tests/assets/sample-config/archive/a.encryption-example.com/fullchain1.pem:30 test path -----BEGIN CERTIFICATE-----
  12. certbot-ci/src/certbot_integration_tests/assets/sample-config/archive/b.encryption-example.com/cert1.pem:1 test path -----BEGIN CERTIFICATE-----
  13. certbot-ci/src/certbot_integration_tests/assets/sample-config/archive/b.encryption-example.com/chain1.pem:1 test path -----BEGIN CERTIFICATE-----
  14. certbot-ci/src/certbot_integration_tests/assets/sample-config/archive/b.encryption-example.com/fullchain1.pem:1 test path -----BEGIN CERTIFICATE-----
  15. certbot-ci/src/certbot_integration_tests/assets/sample-config/archive/b.encryption-example.com/fullchain1.pem:30 test path -----BEGIN CERTIFICATE-----
  16. certbot-ci/src/certbot_integration_tests/assets/sample-config/archive/c.encryption-example.com/chain.pem:1 test path -----BEGIN CERTIFICATE-----
  17. certbot-ci/src/certbot_integration_tests/assets/sample-config/archive/c.encryption-example.com/fullchain.pem:19 test path -----BEGIN CERTIFICATE-----
  18. certbot-ci/src/certbot_integration_tests/assets/sample-config/csr/0000_csr-certbot.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  19. certbot-ci/src/certbot_integration_tests/assets/sample-config/csr/0001_csr-certbot.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  20. certbot-ci/src/certbot_integration_tests/assets/sample-config/csr/0002_csr-certbot.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  21. certbot-ci/src/certbot_integration_tests/assets/sample-config/csr/0003_csr-certbot.pem:1 test path -----BEGIN CERTIFICATE REQUEST-----
  22. certbot-compatibility-test/src/certbot_compatibility_test/testdata/empty_cert.pem:1 test path -----BEGIN CERTIFICATE-----
  23. certbot/src/certbot/tests/testdata/cert_2048.pem:1 test path -----BEGIN CERTIFICATE-----
  24. certbot/src/certbot/tests/testdata/cert_fullchain_2048.pem:1 test path -----BEGIN CERTIFICATE-----
  25. certbot/src/certbot/tests/testdata/cert_fullchain_2048.pem:21 test path -----BEGIN CERTIFICATE-----
  26. certbot/src/certbot/tests/testdata/cert_intermediate_1.pem:1 test path -----BEGIN CERTIFICATE-----
  27. certbot/src/certbot/tests/testdata/cert_intermediate_2.pem:1 test path -----BEGIN CERTIFICATE-----
  28. certbot/src/certbot/tests/testdata/cert_leaf.pem:1 test path -----BEGIN CERTIFICATE-----
  29. certbot/src/certbot/tests/testdata/ocsp_certificate.pem:1 test path -----BEGIN CERTIFICATE-----
  30. certbot/src/certbot/tests/testdata/ocsp_responder_certificate.pem:1 test path -----BEGIN CERTIFICATE-----
  31. certbot/src/certbot/tests/testdata/sample-archive-ec/chain1.pem:1 test path -----BEGIN CERTIFICATE-----
  32. certbot/src/certbot/tests/testdata/sample-archive-ec/fullchain1.pem:19 test path -----BEGIN CERTIFICATE-----
  33. certbot/src/certbot/tests/testdata/sample-archive/cert1.pem:1 test path -----BEGIN CERTIFICATE-----
  34. certbot/src/certbot/tests/testdata/sample-archive/chain1.pem:1 test path -----BEGIN CERTIFICATE-----
  35. certbot/src/certbot/tests/testdata/sample-archive/fullchain1.pem:1 test path -----BEGIN CERTIFICATE-----
  36. certbot/src/certbot/tests/testdata/sample-archive/fullchain1.pem:29 test path -----BEGIN CERTIFICATE-----
pem.certificate
RSA Quantum-vulnerable Recorded traffic 23 places See details

RSA key generated with pyca/cryptography

`rsa.generate_private_key()`. The `key_size` argument is read where it is a literal and reported on the finding; it does not change the classification, because Shor is polynomial in the modulus size.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-KEM-768 for encryption and ML-DSA-65 for signatures.

  1. acme/examples/http01_example.py:72 test path pkey = rsa.generate_private_key(public_exponent=65537, key_size=CERT_PKEY_BITS)
  2. acme/examples/http01_example.py:161 test path key=rsa.generate_private_key(public_exponent=65537,
  3. acme/src/acme/crypto_util.py:81 rsa.RSAPrivateKey,
  4. certbot-ci/src/certbot_integration_tests/certbot_tests/assertions.py:8 test path from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
  5. certbot-ci/src/certbot_integration_tests/certbot_tests/assertions.py:49 test path assert isinstance(key, RSAPrivateKey)
  6. certbot-ci/src/certbot_integration_tests/utils/misc.py:216 test path key: Union[rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey]
  7. certbot-ci/src/certbot_integration_tests/utils/pebble_ocsp_server.py:17 test path from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
  8. certbot-ci/src/certbot_integration_tests/utils/pebble_ocsp_server.py:33 test path Union[RSAPrivateKey, EllipticCurvePrivateKey],
  9. certbot/src/certbot/_internal/renewal.py:754 if isinstance(key, rsa.RSAPrivateKey):
  10. certbot/src/certbot/_internal/storage.py:20 from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
  11. certbot/src/certbot/_internal/storage.py:1095 def _private_key(self) -> Union[RSAPrivateKey, EllipticCurvePrivateKey]:
  12. certbot/src/certbot/_internal/storage.py:1102 return cast(Union[RSAPrivateKey, EllipticCurvePrivateKey], key)
  13. certbot/src/certbot/_internal/storage.py:1111 if isinstance(key, RSAPrivateKey):
  14. certbot/src/certbot/_internal/storage.py:1122 if isinstance(key, RSAPrivateKey):
  15. certbot/src/certbot/crypto_util.py:35 from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
  16. certbot/src/certbot/crypto_util.py:259 key: Union[rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey]
  17. certbot/src/certbot/crypto_util.py:264 key = rsa.generate_private_key(public_exponent=65537, key_size=bits)
  18. certbot/src/certbot/crypto_util.py:357 MLKEM1024PublicKey, RSAPublicKey,
  19. certbot/src/certbot/crypto_util.py:363 :param RSAPublicKey/EllipticCurvePublicKey public_key: the public_key to check signature
  20. certbot/src/certbot/crypto_util.py:371 if isinstance(public_key, RSAPublicKey):
  21. certbot/src/certbot/tests/util.py:27 test path from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
  22. certbot/src/certbot/tests/util.py:122 test path def load_rsa_private_key_pem(*names: str) -> RSAPrivateKey:
  23. certbot/src/certbot/tests/util.py:128 test path assert isinstance(key, RSAPrivateKey)
py.cryptography.rsa · CWE-327
TLS Quantum-vulnerable Recorded traffic 16 places See details

TLS versions pinned in configuration

An `ssl_protocols` or `SSLProtocol` directive. SSLv3, TLS 1.0 and TLS 1.1 are withdrawn.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Every TLS cipher suite in general use negotiates a classical key exchange, so a recorded session is decryptable once that exchange falls.

What to do. TLS 1.2 as the floor, TLS 1.3 preferred.

  1. certbot-ci/src/certbot_integration_tests/assets/sample-config/options-ssl-apache.conf:6 test path SSLProtocol all -SSLv2 -SSLv3
  2. certbot-compatibility-test/nginx/nginx-roundtrip-testdata/guide-to-nginx-ssl-spdy-hsts/nginx.conf:47 test path
  3. certbot-compatibility-test/nginx/nginx-roundtrip-testdata/imapproxyexample/nginx.conf:15 test path ssl_protocols TLSv1 SSLv3;
  4. certbot-compatibility-test/nginx/nginx-roundtrip-testdata/iredmail/iredadmin.conf:9 test path ssl_protocols SSLv3 TLSv1;
  5. certbot-compatibility-test/nginx/nginx-roundtrip-testdata/iredmail/nginx.conf:40 test path ssl_protocols SSLv2 SSLv3 TLSv1;
  6. certbot/src/certbot/_internal/plugins/apache/tls_configs/current-options-ssl-apache.conf:10 SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
  7. certbot/src/certbot/_internal/plugins/apache/tls_configs/old-options-ssl-apache.conf:14 SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
  8. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/failing/missing-double-quote-1724.conf:7 test path
  9. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/failing/multivhost-1093b.conf:172 test path SSLProtocol All -SSLv2 -SSLv3
  10. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/failing/multivhost-1093b.conf:466 test path SSLProtocol All -SSLv2 -SSLv3
  11. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/passing/ipv6-1143b.conf:13 test path SSLProtocol all -SSLv2 -SSLv3
  12. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/passing/ipv6-1143d.conf:13 test path SSLProtocol all -SSLv2 -SSLv3
  13. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/passing/missing-quote-1724.conf:7 test path
  14. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/passing/two-blocks-one-line-1693.conf:11 test path SSLProtocol all -SSLv2 -SSLv3
  15. certbot/src/certbot/_internal/tests/plugins/apache/testdata/centos7_apache/apache/httpd/conf.d/ssl.conf:75 test path SSLProtocol all -SSLv2
  16. certbot/src/certbot/_internal/tests/plugins/apache/testdata/gentoo_apache/apache/apache2/vhosts.d/00_default_ssl_vhost.conf:27 test path SSLProtocol ALL -SSLv2 -SSLv3
config.tls-protocols · CWE-757
RSA2048-bit Quantum-vulnerable Recorded traffic 9 places See details

Private key committed to the repository

A PEM private-key block. The header names the algorithm where the format is the legacy one; for PKCS#8 the algorithm OID is read out of the DER. A private key in version control is a present-day incident before it is a quantum question.

A secret key is stored in this repository's files. Anyone who can read the repository can use it. This needs attention today, regardless of quantum computers.

What to do. Revoke and rotate the key, then keep key material out of the repository. Record the algorithm in the inventory.

pem.private-key · CWE-321, CWE-327
TLS Quantum-vulnerable Recorded traffic 8 places See details

TLS cipher suites pinned in configuration

An `ssl_ciphers`, `SSLCipherSuite` or `ssl-default-bind-ciphers` directive. Every suite available today uses a classical key exchange; a suite naming RC4, DES, 3DES, EXPORT or NULL is broken now.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Every TLS cipher suite in general use negotiates a classical key exchange, so a recorded session is decryptable once that exchange falls.

What to do. Remove anything below TLS 1.2. The key exchange changes when the server software offers a hybrid group, not before.

  1. certbot/src/certbot/_internal/plugins/apache/tls_configs/current-options-ssl-apache.conf:12 SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-G
  2. certbot/src/certbot/_internal/plugins/apache/tls_configs/old-options-ssl-apache.conf:15 SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-G
  3. certbot/src/certbot/_internal/plugins/nginx/tls_configs/options-ssl-nginx-old.conf:16
  4. certbot/src/certbot/_internal/plugins/nginx/tls_configs/options-ssl-nginx-tls12-only.conf:17
  5. certbot/src/certbot/_internal/plugins/nginx/tls_configs/options-ssl-nginx-tls13-session-tix-on.conf:16
  6. certbot/src/certbot/_internal/plugins/nginx/tls_configs/options-ssl-nginx.conf:13
  7. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/failing/missing-double-quote-1724.conf:9 test path SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRS$
  8. certbot/src/certbot/_internal/tests/plugins/apache/apache-conf-files/passing/missing-quote-1724.conf:9 test path SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRS$
config.tls-ciphers · CWE-757
ECDSA256-bitsecg/secp256r1 Quantum-vulnerable 7 places See details

X.509 certificate

A PEM certificate. The subject public-key algorithm and key size are read from the SubjectPublicKeyInfo structure, and the not-after date is reported so certificates that outlive the migration window are visible.

This is a digital identity document. Its expiry date matters: one valid for many years locks in today's algorithms for that long.

What to do. Shorten certificate lifetimes so re-issuing with a post-quantum key is routine.

pem.certificate
ECDSA256-bitsecg/secp256r1 Quantum-vulnerable 6 places See details

Elliptic-curve key generated with pyca/cryptography

`ec.generate_private_key()`. The curve is read from the argument and normalised onto the CycloneDX 1.7 curve registry.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-DSA-65 for signatures. If the key feeds ECDH, treat it as key establishment and prioritise it above signatures.

  1. acme/src/acme/_internal/tests/client_test.py:652 test path key = ec.generate_private_key(ec.SECP256R1())
  2. certbot/src/certbot/_internal/tests/renewal_test.py:24 test path key = ec.generate_private_key(ec.SECP256R1())
  3. certbot/src/certbot/_internal/tests/san_test.py:70 test path key = ec.generate_private_key(ec.SECP256R1())
  4. certbot/src/certbot/_internal/tests/san_test.py:89 test path key = ec.generate_private_key(ec.SECP256R1())
  5. certbot/src/certbot/_internal/tests/san_test.py:113 test path key = ec.generate_private_key(ec.SECP256R1())
  6. certbot/src/certbot/_internal/tests/san_test.py:134 test path key = ec.generate_private_key(ec.SECP256R1())
py.cryptography.ec · CWE-327
RSA Quantum-vulnerable Recorded traffic 5 places See details

Private key committed to the repository

A PEM private-key block. The header names the algorithm where the format is the legacy one; for PKCS#8 the algorithm OID is read out of the DER. A private key in version control is a present-day incident before it is a quantum question.

A secret key is stored in this repository's files. Anyone who can read the repository can use it. This needs attention today, regardless of quantum computers.

What to do. Revoke and rotate the key, then keep key material out of the repository. Record the algorithm in the inventory.

  1. acme/src/acme/_internal/tests/testdata/rsa1024_key.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
  2. acme/src/acme/_internal/tests/testdata/rsa256_key.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
  3. acme/src/acme/_internal/tests/testdata/rsa4096_key.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
  4. acme/src/acme/_internal/tests/testdata/rsa512_key.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
  5. certbot/src/certbot/tests/testdata/rsa512_key.pem:1 test path -----BEGIN RSA PRIVATE KEY-----
pem.private-key · CWE-321, CWE-327
ECDSA Quantum-vulnerable 4 places See details

Private key committed to the repository

A PEM private-key block. The header names the algorithm where the format is the legacy one; for PKCS#8 the algorithm OID is read out of the DER. A private key in version control is a present-day incident before it is a quantum question.

A secret key is stored in this repository's files. Anyone who can read the repository can use it. This needs attention today, regardless of quantum computers.

What to do. Revoke and rotate the key, then keep key material out of the repository. Record the algorithm in the inventory.

  1. certbot/src/certbot/tests/testdata/ec_prime256v1_key.pem:4 test path -----BEGIN EC PRIVATE KEY-----
  2. certbot/src/certbot/tests/testdata/ec_secp384r1_key.pem:4 test path -----BEGIN EC PRIVATE KEY-----
  3. certbot/src/certbot/tests/testdata/ec_secp521r1_key.pem:4 test path -----BEGIN EC PRIVATE KEY-----
  4. certbot/src/certbot/tests/testdata/nistp256_key.pem:1 test path -----BEGIN EC PRIVATE KEY-----
pem.private-key · CWE-321, CWE-327
RSA2048-bit Quantum-vulnerable Recorded traffic 3 places See details

RSA key generated with pyca/cryptography

`rsa.generate_private_key()`. The `key_size` argument is read where it is a literal and reported on the finding; it does not change the classification, because Shor is polynomial in the modulus size.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-KEM-768 for encryption and ML-DSA-65 for signatures.

  1. acme/src/acme/_internal/tests/crypto_util_test.py:120 test path self.privkey = rsa.generate_private_key(public_exponent=65537, key_size=2048)
  2. acme/src/acme/_internal/tests/crypto_util_test.py:206 test path privkey = rsa.generate_private_key(public_exponent=65537, key_size=2048)
  3. certbot-ci/src/certbot_integration_tests/utils/misc.py:218 test path key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
py.cryptography.rsa · CWE-327
RSA4096-bit Quantum-vulnerable 3 places See details

X.509 certificate

A PEM certificate. The subject public-key algorithm and key size are read from the SubjectPublicKeyInfo structure, and the not-after date is reported so certificates that outlive the migration window are visible.

This is a digital identity document. Its expiry date matters: one valid for many years locks in today's algorithms for that long.

What to do. Shorten certificate lifetimes so re-issuing with a post-quantum key is routine.

pem.certificate
ECDSA256-bitsecg/secp256r1 Quantum-vulnerable 2 places See details

Private key committed to the repository

A PEM private-key block. The header names the algorithm where the format is the legacy one; for PKCS#8 the algorithm OID is read out of the DER. A private key in version control is a present-day incident before it is a quantum question.

A secret key is stored in this repository's files. Anyone who can read the repository can use it. This needs attention today, regardless of quantum computers.

What to do. Revoke and rotate the key, then keep key material out of the repository. Record the algorithm in the inventory.

pem.private-key · CWE-321, CWE-327
DH Quantum-vulnerable Recorded traffic 1 place See details

Public key file

A PEM public-key block. The algorithm is read from the SubjectPublicKeyInfo.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. Inventory only; a public key is not itself a secret.

  1. certbot/src/certbot/ssl-dhparams.pem:1 -----BEGIN DH PARAMETERS-----
pem.public-key
DSA Quantum-vulnerable 1 place See details

Private key committed to the repository

A PEM private-key block. The header names the algorithm where the format is the legacy one; for PKCS#8 the algorithm OID is read out of the DER. A private key in version control is a present-day incident before it is a quantum question.

A secret key is stored in this repository's files. Anyone who can read the repository can use it. This needs attention today, regardless of quantum computers.

What to do. Revoke and rotate the key, then keep key material out of the repository. Record the algorithm in the inventory.

  1. acme/src/acme/_internal/tests/testdata/dsa512_key.pem:7 test path -----BEGIN DSA PRIVATE KEY-----
pem.private-key · CWE-321, CWE-327
ECDSA384-bitsecg/secp384r1 Quantum-vulnerable 1 place See details

Private key committed to the repository

A PEM private-key block. The header names the algorithm where the format is the legacy one; for PKCS#8 the algorithm OID is read out of the DER. A private key in version control is a present-day incident before it is a quantum question.

A secret key is stored in this repository's files. Anyone who can read the repository can use it. This needs attention today, regardless of quantum computers.

What to do. Revoke and rotate the key, then keep key material out of the repository. Record the algorithm in the inventory.

pem.private-key · CWE-321, CWE-327
ECDSA384-bitsecg/secp384r1 Quantum-vulnerable 1 place See details

Elliptic-curve key generated with pyca/cryptography

`ec.generate_private_key()`. The curve is read from the argument and normalised onto the CycloneDX 1.7 curve registry.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-DSA-65 for signatures. If the key feeds ECDH, treat it as key establishment and prioritise it above signatures.

  1. certbot-ci/src/certbot_integration_tests/utils/misc.py:220 test path key = ec.generate_private_key(ec.SECP384R1())
py.cryptography.ec · CWE-327
ECDSA Quantum-vulnerable 1 place See details

Elliptic-curve key generated with pyca/cryptography

`ec.generate_private_key()`. The curve is read from the argument and normalised onto the CycloneDX 1.7 curve registry.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-DSA-65 for signatures. If the key feeds ECDH, treat it as key establishment and prioritise it above signatures.

  1. certbot/src/certbot/crypto_util.py:274 key = ec.generate_private_key(
py.cryptography.ec · CWE-327
RSA4096-bit Quantum-vulnerable Recorded traffic 1 place See details

Private key committed to the repository

A PEM private-key block. The header names the algorithm where the format is the legacy one; for PKCS#8 the algorithm OID is read out of the DER. A private key in version control is a present-day incident before it is a quantum question.

A secret key is stored in this repository's files. Anyone who can read the repository can use it. This needs attention today, regardless of quantum computers.

What to do. Revoke and rotate the key, then keep key material out of the repository. Record the algorithm in the inventory.

  1. certbot-ci/src/certbot_integration_tests/assets/key.pem:1 test path -----BEGIN PRIVATE KEY-----
pem.private-key · CWE-321, CWE-327
RSA Quantum-vulnerable Recorded traffic 1 place See details

Public key declared as a JSON Web Key

A `kty` field, with the curve read from the sibling `crv` where the family needs one. A JWKS document declares a key without naming an algorithm anywhere, so it is invisible to a scan that only looks for `alg`.

This file publishes the public keys other systems use to check this system's signatures. Everyone who trusts these keys has to accept the new kind of key before the old ones can be retired.

What to do. A published JWKS is what relying parties trust. It has to accept a post-quantum key type before the keys behind it can change, so put it early in the migration order.

  1. certbot-ci/src/certbot_integration_tests/assets/sample-config/accounts/acme-staging.api.letsencrypt.org/directory/48d6b9e8d767eccf7e4d877d6ffa81e3/private_key.json:1 test path {"e": "AQAB", "d": "W410Wny96RO4qJ207KGQ3RSn0KAwqb93JBMHWU1yS9H3fN_2eCpFYdMLNFI9t1__nW1okeUioEfvMN_YW-G9krw97kVdZ63MfbeJCf35Onc8VZhAnk_3V8MtS26Of8ml0tTYhlQ65nuzhvHbY7aP-Uk260oDN-AbCCVhu5G4CQiMY6sdtCc8YkB6gK7SK874oWU7ogvAIPtNtEI-AXDUBYNAfoh3
jose.jwk · CWE-327
X25519255-bitother/Curve25519 Quantum-vulnerable Recorded traffic 1 place See details

X25519 key agreement

`X25519PrivateKey.generate()`. X25519 is the best classical key exchange available and is still a discrete-logarithm problem, so Shor solves it.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. Hybrid X25519+ML-KEM-768 keeps this exact code as the classical half.

  1. acme/src/acme/_internal/tests/crypto_util_test.py:264 test path privkey = x25519.X25519PrivateKey.generate()
py.cryptography.x25519 · CWE-327
SHA-256 Reduced margin Renamed import 3 places See details

Hash function in use

`hashlib.sha256()` and friends. The digest is read from the call, so SHA-384 and above are inventory while the broken ones are reported separately.

A quantum computer weakens this but does not break it. Increasing the key or digest size restores the margin. Pre-image resistance falls to about 128 bits of quantum work. Adequate for most uses; SHA-384 restores the full margin where a signature must last decades.

What to do. SHA-256 as the floor, SHA-384 where the digest protects something long-lived.

  1. acme/src/acme/challenges.py:265 return jose.b64encode(hashlib.sha256(self.key_authorization(
  2. certbot/src/certbot/crypto_util.py:563 sha256 = hashlib.sha256()
  3. tests/modification-check.py:30 test path hash_object = hashlib.sha256()
py.hashlib
unknown Could not be determined 4 places See details

Cryptographic library in the dependency manifest

A dependency known to implement classical asymmetric cryptography. Its presence is inventory, not a finding about this codebase: the library may never be called with a quantum-vulnerable algorithm.

The project depends on a cryptography library. Listed so the inventory is complete; it is not by itself a problem.

What to do. Check the version. Several of these libraries have shipped ML-KEM and ML-DSA support since 2024, so the migration may need an upgrade rather than a replacement.

  1. acme/pyproject.toml:29 "cryptography>=47.0.0",
  2. certbot-ci/pyproject.toml:29 "cryptography",
  3. certbot/setup.py:32 'cryptography>=47.0.0',
  4. tools/requirements.txt:35 cryptography==50.0.0 ; python_version >= "3.10" and python_version < "4.0"
dep.crypto-library
CSPRNG Quantum-safe 2 places See details

Random number generation

`secrets.token_bytes()`, `os.urandom()` or `ssl.RAND_bytes()`. Recorded so the inventory names its randomness source.

This is where the software gets its random numbers. Quantum computers do not weaken it.

What to do. No action. `random.random()` is a separate, present-day defect if it reaches key material.

  1. certbot-compatibility-test/src/certbot_compatibility_test/test_driver.py:112 test path token=os.urandom(int(challenges.HTTP01.TOKEN_SIZE)))
  2. certbot/src/certbot/_internal/plugins/apache/apache_util.py:119 return binascii.hexlify(os.urandom(16)).decode("utf-8")
py.rng

Cryptographic assets

Algorithm Assessment What it means Occurrences
RSA Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 114
TLS Quantum-vulnerable Every TLS cipher suite in general use negotiates a classical key exchange, so a recorded session is decryptable once that exchange falls. 25
ECDSA Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 22
RSA-1024 Already broken A modulus of 1024 bits or less is below the NIST SP 800-57 floor and is within reach of classical factorisation. Shor is not the nearest problem here. 20
MD5 Already broken Practical chosen-prefix collisions exist; MD5 has no remaining security as a digest. 8
RC4 Already broken RC4 keystream biases break it classically; it is prohibited in TLS by RFC 7465. 8
SHA-256 Reduced margin Pre-image resistance falls to about 128 bits of quantum work. Adequate for most uses; SHA-384 restores the full margin where a signature must last decades. 7
CSPRNG Quantum-safe A cryptographically secure random number generator provided by the platform. Not weakened by a quantum computer. 2
DH Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 1
DSA Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 1
X25519 Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 1

Imported cryptographic libraries

Library Files
cryptography — pyca/cryptography — RSA, elliptic curves, TLS primitives 30
ssl — the TLS client and server 1
hashlib — the standard digests, including the broken ones 4