Skip to content

fix(security): resolve CVE-2026-26007 by migrating deprecated OpenSSL.crypto.verify and unblocking cryptography >= 46.0.5#1021

Open
ascii-dev wants to merge 1 commit intoIdentityPython:masterfrom
ascii-dev:bump_openssl_cryptography_versions
Open

fix(security): resolve CVE-2026-26007 by migrating deprecated OpenSSL.crypto.verify and unblocking cryptography >= 46.0.5#1021
ascii-dev wants to merge 1 commit intoIdentityPython:masterfrom
ascii-dev:bump_openssl_cryptography_versions

Conversation

@ascii-dev
Copy link

@ascii-dev ascii-dev commented Mar 9, 2026

Description

The feature or problem addressed by this PR

This PR resolves the dependency deadlock preventing the mitigation of CVE-2026-26007 (elliptic curve subgroup validation vulnerability).

Currently, upgrading the cryptography package to a secure version is blocked by the upper bound constraint on pyopenssl < 24.3.0. That constraint exists because OpenSSL.crypto.verify was deprecated and subsequently removed in pyopenssl 24.3.0. We need a way to verify signatures without relying on the removed API so we can bump both packages and secure downstream users.

Closes #1017

What your changes do and why you chose this solution

To unblock the security patch, this PR refactors the signature verification layer in src/saml2/cert.py.

Technical Changes:

  • Migrated Verification API: Replaced the removed OpenSSL.crypto.verify API with direct cryptography.hazmat.primitives.asymmetric implementations.
  • Handles RSA keys via RSAPublicKey.verify() with PKCS1v15 padding.
  • Handles EC keys via EllipticCurvePublicKey.verify() with ECDSA.
  • Removed the < 24.3.0 upper bound on pyopenssl.
  • Bumped cryptography >= 46.0.5 to explicitly enforce the CVE-2026-26007 mitigation.
  • Updated types-pyopenssl to >= 24.0.0 to maintain type compatibility.
  • Bumped the minimum supported Python version from 3.9 to 3.9.2 to align with the new upstream package constraints.

Why this solution:
The project's remaining reliance on pyopenssl for certificate creation and loading remains completely untouched and functional. Existing tests pass locally with xmlsec1 installed.

Checklist

  • Checked that no other issues or pull requests exist for the same issue/change
  • Added tests covering the new functionality
  • Updated documentation OR the change is too minor to be documented
  • Updated CHANGELOG.md OR changes are insignificant

@peppelinux
Copy link
Member

@ascii-dev I got your contribution here:
https://github.com/italia/iam-proxy-italia/releases/tag/v3.2.0

thank you

@c00kiemon5ter ^

@ascii-dev
Copy link
Author

@peppelinux Awesome to see this actively unblocking the v3.2.0 release for iam-proxy-italia! Glad it was helpful.

@c00kiemon5ter - let me know if there are any changes you'd like me to add to get this aligned for a merge.

Copy link

@robin92 robin92 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good change though I'd take care of

issue: cert_crypto.signature_hash_algorithm can return None which would cause a TypeError from _ec.ECDSA call.

and add some tests before merging this.

ipdb = "^0.13.9"
mypy = "^1.0.0"
types-pyopenssl = "^23.0.0.3"
types-pyopenssl = ">=24.0.0"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Most likely, you no longer need this package as type annotations are part of pyopenssl since 24.2.1.

Source

Note: The pyOpenSSL package includes type annotations or type stubs since version 24.2.1. Please uninstall the types-pyOpenSSL package if you use this or a newer version.

"Topic :: Software Development :: Libraries :: Python Modules",
]
requires-python = ">= 3.9"
requires-python = ">= 3.9.2"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: If there weren't any fixes that you need, then I'd avoid bumping this.

return False, f"Unsupported public key type: {type(ca_public_key)}"
return True, "Signed certificate is valid and correctly signed by CA certificate."
except crypto.Error as e:
except Exception as e:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Be specific about the exception specified as the error message returned is quite specific.

Also, notice that the exception at l.355 would cover all the cases missed here either way. The message there would be more suited to the situation that occurred.

Btw, you probably should catch cryptography.exceptions.InvalidSignature here.

ca_public_key.verify(
cert_crypto.signature,
cert_crypto.tbs_certificate_bytes,
_ec.ECDSA(cert_crypto.signature_hash_algorithm),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: cert_crypto.signature_hash_algorithm can return None which would cause a TypeError from _ec.ECDSA call.

I'd handle this case explicitly above the try-except like this

if cert_crypto.signature_hash_algorithm is None:
    return False, "Unsupported signature algorithm (no hash algorithm present)."

cert_crypto = saml2.cryptography.pki.load_pem_x509_certificate(cert_str)
cert_crypto = saml2.cryptography.pki.load_pem_x509_certificate(cert_str_bytes)
ca_cert_crypto = saml2.cryptography.pki.load_pem_x509_certificate(signing_cert_bytes)
ca_public_key = ca_cert_crypto.public_key()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider migrating OpenSSL-based expiry and CN checks to the cryptography API.

The CA certificate seems to be loaded second time here.

  • First via crypto.load_certificate() for the expiry/CN checks (lines 309–325)
  • Second via saml2.cryptography.pki.load_pem_x509_certificate() for signature verification

These hold the same data. Consider whether the OpenSSL-based expiry and CN checks could also migrate to the cryptography API — it would eliminate the double parse and reduce the OpenSSL surface area in this method, which is the stated direction of the change.

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.

3 participants