Before reporting an issue
Area
oid4vc
Describe the bug
The AttestationValidatorUtil.java component contains a conditional check that explicitly skips CertPathValidator.validate() if the first certificate in the provided x5c chain is detected as self-signed. This behavior, intended for easier testing in dev environments, creates a significant security vulnerability in production. Because the validation is bypassed, Keycloak accepts the public key from the self-signed certificate as a valid, attested key for credential binding. An attacker can generate a self-signed certificate and present it during the OID4VC issuance flow to forge hardware-backed attestation claims.
Version
26.4.5
Regression
Expected behavior
All certificates provided in the x5c header for attestation must be validated against the configured Trust Anchors using the PKIX algorithm. If a certificate is self-signed, it should only be accepted if it is explicitly present in the trust store; otherwise, the attestation should be rejected.
Actual behavior
The code evaluates if firstCert.getSubjectX500Principal().equals(firstCert.getIssuerX500Principal()). If this evaluates to true, the PKIX validation block is entirely skipped. The public key from this unvalidated certificate is then used to create a JWK and return a verifier, effectively trusting any self-signed certificate.
How to Reproduce?
-
Enable the experimental OID4VC (OpenID for Verifiable Credentials) feature in Keycloak.
-
Configure a credential issuer that requires hardware attestation for key binding.
-
As an authenticated user, initiate the credential issuance flow.
-
Submit an issuance request including an attestation proof where the x5c header contains a freshly generated self-signed certificate (not present in Keycloak's trust store).
-
Observe that Keycloak accepts the attestation and issues the credential bound to the attacker's key, despite the lack of a valid trust chain to a hardware vendor's root.
Anything else?
No response
Before reporting an issue
Area
oid4vc
Describe the bug
The AttestationValidatorUtil.java component contains a conditional check that explicitly skips CertPathValidator.validate() if the first certificate in the provided x5c chain is detected as self-signed. This behavior, intended for easier testing in dev environments, creates a significant security vulnerability in production. Because the validation is bypassed, Keycloak accepts the public key from the self-signed certificate as a valid, attested key for credential binding. An attacker can generate a self-signed certificate and present it during the OID4VC issuance flow to forge hardware-backed attestation claims.
Version
26.4.5
Regression
Expected behavior
All certificates provided in the x5c header for attestation must be validated against the configured Trust Anchors using the PKIX algorithm. If a certificate is self-signed, it should only be accepted if it is explicitly present in the trust store; otherwise, the attestation should be rejected.
Actual behavior
The code evaluates if firstCert.getSubjectX500Principal().equals(firstCert.getIssuerX500Principal()). If this evaluates to true, the PKIX validation block is entirely skipped. The public key from this unvalidated certificate is then used to create a JWK and return a verifier, effectively trusting any self-signed certificate.
How to Reproduce?
Enable the experimental OID4VC (OpenID for Verifiable Credentials) feature in Keycloak.
Configure a credential issuer that requires hardware attestation for key binding.
As an authenticated user, initiate the credential issuance flow.
Submit an issuance request including an attestation proof where the x5c header contains a freshly generated self-signed certificate (not present in Keycloak's trust store).
Observe that Keycloak accepts the attestation and issues the credential bound to the attacker's key, despite the lack of a valid trust chain to a hardware vendor's root.
Anything else?
No response