Summary
JwkSet derives Deserialize, and AlgorithmParameters is an untagged enum with no fallback variant. A key whose kty (or alg) is not one of the known variants therefore fails deserialization of the entire JwkSet, not just that key. Per RFC 7517 section 5 an unrecognised key should be ignored, so one post-quantum key in a published JWKS breaks parsing of the classical keys alongside it.
Reproduction
A JWKS with a classical key and one post-quantum ML-DSA key (kty: "AKP", RFC 9964):
let set: jsonwebtoken::jwk::JwkSet = serde_json::from_str(mixed_jwks)?;
// Err: data did not match any variant of untagged enum AlgorithmParameters
Measured against 10.4.0 (fails on the unknown kty) and 9.3.1 (fails on the unknown alg). The set deserializes fine once the AKP key is removed. Fixture and probe available on request.
Why this matters
RFC 7517 section 5: "Implementations SHOULD ignore JWKs within a JWK Set that use kty values that are not understood by them." As post-quantum migration begins (ML-DSA in Node today, Go stdlib in 1.27, RFC 9964 defines the AKP JWK form), issuers will publish AKP keys into key sets that jsonwebtoken consumers read. Because the whole JwkSet fails to deserialize, those consumers stop verifying every signature from that issuer, including classical RS256/ES256, on a key publication they do not control.
Suggested fix
Two options, either works:
- Add a catch-all variant to
AlgorithmParameters (for example an Other/Unknown arm, or #[serde(other)] where applicable) so an unknown key deserializes into an inert variant and JwkSet::find(kid) simply never selects it; or
- Deserialize
keys as a Vec of raw values and skip members that fail to parse into a Jwk, keeping the recognised keys.
Either implements the RFC section 5 SHOULD without changing behaviour for recognised keys.
Offer
Happy to share the reproduction harness (mixed classical + AKP JWKS plus a control) and to open a PR.
Summary
JwkSetderivesDeserialize, andAlgorithmParametersis an untagged enum with no fallback variant. A key whosekty(oralg) is not one of the known variants therefore fails deserialization of the entireJwkSet, not just that key. Per RFC 7517 section 5 an unrecognised key should be ignored, so one post-quantum key in a published JWKS breaks parsing of the classical keys alongside it.Reproduction
A JWKS with a classical key and one post-quantum ML-DSA key (
kty: "AKP", RFC 9964):Measured against 10.4.0 (fails on the unknown
kty) and 9.3.1 (fails on the unknownalg). The set deserializes fine once the AKP key is removed. Fixture and probe available on request.Why this matters
RFC 7517 section 5: "Implementations SHOULD ignore JWKs within a JWK Set that use
ktyvalues that are not understood by them." As post-quantum migration begins (ML-DSA in Node today, Go stdlib in 1.27, RFC 9964 defines theAKPJWK form), issuers will publish AKP keys into key sets that jsonwebtoken consumers read. Because the wholeJwkSetfails to deserialize, those consumers stop verifying every signature from that issuer, including classical RS256/ES256, on a key publication they do not control.Suggested fix
Two options, either works:
AlgorithmParameters(for example anOther/Unknownarm, or#[serde(other)]where applicable) so an unknown key deserializes into an inert variant andJwkSet::find(kid)simply never selects it; orkeysas aVecof raw values and skip members that fail to parse into aJwk, keeping the recognised keys.Either implements the RFC section 5 SHOULD without changing behaviour for recognised keys.
Offer
Happy to share the reproduction harness (mixed classical + AKP JWKS plus a control) and to open a PR.