Skip to content

Comments

fix: harden JWT and X.509 SVID validation and error handling#375

Merged
maxlambrecht merged 3 commits intoHewlettPackard:mainfrom
maxlambrecht:fix/jwt-x509-validation-correctness
Feb 1, 2026
Merged

fix: harden JWT and X.509 SVID validation and error handling#375
maxlambrecht merged 3 commits intoHewlettPackard:mainfrom
maxlambrecht:fix/jwt-x509-validation-correctness

Conversation

@maxlambrecht
Copy link
Collaborator

Summary

This PR fixes several correctness and validation issues in the JWT-SVID and X.509-SVID implementations, with the goal of aligning behavior more closely with the SPIFFE specifications and avoiding silent acceptance of invalid identity material.

On the JWT-SVID side, the changes ensure that a token is rejected early if the sub claim is missing or empty, rather than relying on downstream SPIFFE ID parsing to fail implicitly. The JWT decoding path is also tightened to use an already-validated algorithm when verifying signatures, and expiration (exp) is now treated explicitly as a numeric value during validation to avoid type-related edge cases.

On the X.509-SVID side, validation is made stricter and more explicit. The code now fails with clear validation errors when required extensions (SubjectAlternativeName, BasicConstraints, KeyUsage) are missing, instead of propagating low-level exceptions. The leaf certificate validation enforces that exactly one SPIFFE URI SAN is present, as required by the SPIFFE X.509-SVID specification, and rejects certificates that contain multiple SPIFFE IDs.

These changes do not introduce API changes. They are intended to improve security, correctness, and spec compliance, and to make invalid SVIDs fail fast with clear, intentional errors.

Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>
Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>
Copy link
Contributor

@amartinezfayo amartinezfayo left a comment

Choose a reason for hiding this comment

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

Thank you @maxlambrecht, this is a great improvement!
I have some comments / suggestions. My main concern is around the validation logic for URI SAN.

'Certificate contains multiple SPIFFE IDs in the URI SAN'
)

return SpiffeId(spiffe_uris[0])
Copy link
Contributor

Choose a reason for hiding this comment

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

This could raise an exception if the SPIFFE URI is malformed. Maybe it could be wrapped in a try-catch to provide clearer error context?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

)
return SpiffeId(sans[0])

if len(spiffe_uris) > 1:
Copy link
Contributor

Choose a reason for hiding this comment

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

It doesn't seem like we have test coverage for this new validation. I think that it would be great to have it covered by tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added test coverage.

Comment on lines 272 to 283
uri_sans = ext.value.get_values_for_type(x509.UniformResourceIdentifier)
spiffe_uris = [uri for uri in uri_sans if uri.startswith(spiffe_id.SCHEME_PREFIX)]

if len(spiffe_uris) == 0:
raise InvalidLeafCertificateError(
'Certificate does not contain a SPIFFE ID in the URI SAN'
)
return SpiffeId(sans[0])

if len(spiffe_uris) > 1:
raise InvalidLeafCertificateError(
'Certificate contains multiple SPIFFE IDs in the URI SAN'
)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that this validation logic checks only SPIFFE URIs, not all URI SANs. This is a problem because the spec says that "An X.509 SVID MUST contain exactly one URI SAN, and by extension, exactly one SPIFFE ID.".
The way I see this code, a certificate with spiffe://example.org/service + https://example.org would still be accepted by py-spiffe.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's correct. Fixed

Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>
@maxlambrecht
Copy link
Collaborator Author

Thanks for the great review, @amartinezfayo!

Copy link
Contributor

@amartinezfayo amartinezfayo left a comment

Choose a reason for hiding this comment

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

Thank you @maxlambrecht, looks great! 🎉

@maxlambrecht maxlambrecht merged commit 4237f71 into HewlettPackard:main Feb 1, 2026
6 checks passed
@maxlambrecht maxlambrecht deleted the fix/jwt-x509-validation-correctness branch February 1, 2026 14:56
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.

2 participants