fix(schema): accept valid SD-JWT serializations in checkout_mandate pattern#623
Closed
vishkaty wants to merge 2 commits into
Closed
fix(schema): accept valid SD-JWT serializations in checkout_mandate pattern#623vishkaty wants to merge 2 commits into
vishkaty wants to merge 2 commits into
Conversation
…attern The checkout_mandate pattern could not match any serialization that is valid for the format the field is documented to carry: - RFC 9901 compact SD-JWT ends with '~' when no KB-JWT is present; the pattern's (~[A-Za-z0-9_-]+)* groups forbid a trailing tilde. - An SD-JWT with Key Binding ends in a KB-JWT, which contains dots; the tilde-segment character class forbids dots, so every SD-JWT+KB was rejected. - Delegated presentations (as emitted by the AP2 reference implementation) join tokens with '~~', which the pattern also rejects. The only strings the old pattern accepted (a bare compact JWT, or dot-free tilde segments without the trailing tilde) are not valid RFC 9901 serializations. CI never caught this because the complete-request example validates against the base checkout schema, which does not exercise the extension's pattern. The new pattern admits: compact SD-JWT with or without KB-JWT, and '~~' delegate chains of such tokens; it is a strict superset of the old pattern, so no previously-valid payload breaks. Also documents the accepted wire forms in ap2-mandates.md. Fixes Universal-Commerce-Protocol#599 (option 2).
Per adversarial review: the previous pattern let a delegate-chain hop be a bare JWT (e.g. `J~~J`), a shape the AP2 reference verifier rejects (every hop must be a well-formed SD-JWT — at least one disclosure, or a KB-JWT). The back-compat leniency for the old pattern's bare/no-terminator forms now applies only to a single (non-chained) token, not inside chains. Still a strict superset of the original pattern (verified: 30k-string fuzz over the old grammar, zero regressions), and all reference-emitted serializations (1-3 hop chains, KB and no-KB finals, real reference-minted wires) still match.
Contributor
Author
|
Updated the pattern after an internal adversarial pass: chain hops are now required to each be a well-formed SD-JWT (at least one disclosure, or a KB-JWT), so a bare-JWT hop like |
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements option 2 of #599 — opened as a draft so maintainers can confirm that widening the schema (rather than scoping the docs, option 1, or waiting for the binding to settle, option 3) is the intended direction.
Problem
ap2_mandate.json'scheckout_mandatepatterncannot match any serialization that is valid for the format the field is documented to carry:~when no Key Binding JWT is present (the ABNF's trailing tilde is mandatory); the pattern's(~[A-Za-z0-9_-]+)*groups forbid a trailing tilde.~~, also rejected.The only strings the old pattern accepted (a bare compact JWT, or dot-free tilde segments without the trailing tilde) are not valid RFC 9901 serializations. CI never surfaced this: the complete-request example validates against the base checkout schema (
additionalProperties: true, noap2member), so the extension's pattern is never exercised.Change
patternadmitting: compact SD-JWT with or without a trailing KB-JWT, and~~-joined delegate chains of such tokens (non-final hop's trailing tilde stripped at join, per the reference implementation's serialization). It is a strict superset of the old pattern, so no previously-valid payload breaks.descriptionupdated to name the accepted serializations, and a short Wire format note added to ap2-mandates.md. (Doc edit is in the Mandate Structure section — no overlap with docs(ap2): clarify ES512 signature scope #618's algorithm-scope edits.)Validation
u-flag clean), Python, and Rust (ucp-schema); adversarial inputs up to 100 KB show linear-time matching (no catastrophic backtracking).ucp-schema lint source/(96 files pass),scripts/validate_examples.py(276 passed, 0 failed),scripts/test_validate_examples.py(43 passed).ucp-schemavalidator: a real reference-produced chain validates under the new pattern and reproduces the rejection under the old one.Fixes #599.