jws: Verify rejects b64=false without "b64" listed in "crit" - #2102
Merged
Merged
Conversation
v3 backport of #2101. RFC 7797 §3 requires producers that set "b64":false in the protected header to also include "b64" in the "crit" array; §6 ties this to RFC 7515's critical-header-parameter rule. VerifyCompactFast already rejects any b64-bearing message outright (jws.ErrB64Present), but jws.Verify silently accepted the non-conformant shape — b64=false on the wire with no crit, or with a crit that doesn't list "b64". A strictly conformant verifier would compute a different signing input on the same bytes, exactly the cross-implementation disagreement §6 was designed to prevent. Adds validateB64InCritIfFalse in verify_context.go, called from both VerifyMessage and verifyStreaming inside the existing critValidation block. v3 critValidation defaults to false so the new check is opt-in on this branch (use jws.WithCritValidation(true)); v4 critValidation defaults to true so the v4 PR rejects the non-conformant shape by default. Behavior on v3 default config is unchanged. Includes a regression test that mirrors TestVerifyCompactFastRefusesB64False on the slow path. Also extracts the duplicated `{"alg":"HS256","b64":false}` literal into a shared package const to head off the goconst lint warning.
lestrrat
added a commit
that referenced
this pull request
Apr 29, 2026
v3 backport of #2103. RFC 7797 §3 requires producers that set "b64":false to also list "b64" in "crit". Callers who set b64=false typically forget the crit declaration; the resulting JWS is non-conformant and fails to interop with strict verifiers. Auto-add "b64" to the protected header's crit array inside Sign whenever b64=false is set. Idempotent: pre-existing crit with b64 unchanged; crit with other extensions gets "b64" appended; absent crit is created with just "b64". This pairs with the v3 Verify-side change in #2102, which makes jws.Verify (under WithCritValidation(true)) refuse non-conformant b64=false streams. Together they close the producer/verifier gap on v3.
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.
v3 backport of #2101.
RFC 7797 §3 requires producers that set
b64=falseto also listb64incrit; §6 ties this to RFC 7515's critical-header-parameter rule.VerifyCompactFastrejects any b64-bearing message outright;jws.Verifysilently accepted the non-conformant shape (b64=false with no crit, or crit missing b64).Adds
validateB64InCritIfFalsecalled from bothVerifyMessageandverifyStreaminginside the existingcritValidationblock. v3critValidationdefaults to false, so the new check is opt-in here (jws.WithCritValidation(true)); behavior on v3 default config is unchanged. v4's default is true, so the v4 PR rejects the non-conformant shape by default.Regression test mirrors
TestVerifyCompactFastRefusesB64Falseon the slow path. Also extracts the duplicated{"alg":"HS256","b64":false}literal into a shared package const.