{"id":"CVE-2026-69247","aliases":["GHSA-g6cj-pr64-35w5","PYSEC-2026-3552"],"url":"https://o3.security/vulnerability/CVE-2026-69247","summary":"cryptography: PKCS#7 EnvelopedData decryption exposes a Bleichenbacher oracle through distinguishable errors and timing","details":"### Summary\n\n`pkcs7_decrypt_der`, `pkcs7_decrypt_pem`, and `pkcs7_decrypt_smime` reported the\noutcome of decrypting a `RecipientInfo`'s `encryptedKey` in several\ndistinguishable ways, one of which disclosed the exact length recovered from the\nRSA operation. The same distinction was also observable by timing. An\napplication that decrypts attacker-supplied `EnvelopedData` and reflects the\noutcome gives the attacker a Bleichenbacher oracle against the\ncontent-encryption key.\n\nIntroduced in 44.0.0. Fixed in 50.0.0.\n\n### Details\n\nDecryption ran as: RSA PKCS#1 v1.5 decrypt of `encryptedKey` → build an AES\ncipher from the result → AES-CBC decrypt and PKCS#7 unpad. Each stage failed\ndifferently, with no RFC 3218 mitigation:\n\n1. invalid RSA padding → `Decryption failed`\n2. valid padding, bad key length → `Invalid key size (N) for AES.`, disclosing `N`\n3. correct length, wrong key → `Invalid padding bytes.`\n4. the real key → plaintext\n\nCase 1 is reachable only where the linked library lacks implicit rejection:\nOpenSSL 3.0 and 3.1, LibreSSL, and BoringSSL. On OpenSSL 3.2+, used in our wheels,\ninvalid padding instead returns a synthetic plaintext of\npseudorandom length, so the error channel does not distinguish conforming\nciphertexts.\n\nExploitation requires a service that auto-decrypts untrusted `EnvelopedData`\nmatching the victim certificate and answers adaptively at high volume, such as\nan S/MIME gateway or mail filter.\n\n### Fix\n\nPer RFC 3218, the content-encryption algorithm is now resolved before the\nprivate key is used, so the expected key length is known in advance. If the RSA\ndecryption fails or recovers a key of the wrong length, a random key of the\nexpected length is substituted and decryption continues down an identical path.\nAll failures now report identically and perform the same work.\n\n### Not addressed by this fix\n\n`EnvelopedData` does not authenticate its content. Tampering with\n`encryptedContent` alone yields a CBC padding oracle that recovers plaintext at\nroughly 256 queries per byte, without recovering any key, on every backend. This\nis a property of PKCS#7 rather than of this implementation, cannot be fixed in\nthe library, and is now documented.\n\n### Credit\n\nReported by @X1AOxiang.","published":"2026-08-03T21:16:32.047Z","modified":"2026-10-28T02:30:22.686857240Z","cvss":null,"epss":{"score":0.00175,"percentile":0.0729,"asOf":"2026-09-16"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"cryptography","fixedVersion":"50.0.0"}],"fix":{"url":"https://github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f","label":"pyca/cryptography@53fccd9"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/69xxx/CVE-2026-69247.json"},{"type":"ADVISORY","url":"https://github.com/pyca/cryptography/security/advisories/GHSA-g6cj-pr64-35w5"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-69247"},{"type":"FIX","url":"https://github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f"},{"type":"FIX","url":"https://github.com/pyca/cryptography/pull/15369"},{"type":"PACKAGE","url":"https://github.com/pyca/cryptography"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:22.686857240Z"}}