From d8b32e43433c47939e326c2ce191ca3331d2fb20 Mon Sep 17 00:00:00 2001 From: Oskar Eichler Date: Fri, 4 Sep 2026 23:28:56 +0700 Subject: [PATCH] Preserve claims verification state for unencoded payloads --- CHANGELOG.md | 1 + lib/jwt/claims/crit.rb | 9 +++++++-- lib/jwt/encoded_token.rb | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca5c1d897..87693d087 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ **Fixes and enhancements:** +- Preserve claims verification state and reject unsupported critical headers when decoding unencoded payloads [#753](https://github.com/jwt/ruby-jwt/pull/753) - [@OskarEichler](https://github.com/OskarEichler) - Fix rejection of unknown algorithms from JWKs for RFC compliance and pquip [#728](https://github.com/jwt/ruby-jwt/pull/728) - Fix the `Style/DirectiveScope` RuboCop offense failing the build [#752](https://github.com/jwt/ruby-jwt/pull/752) diff --git a/lib/jwt/claims/crit.rb b/lib/jwt/claims/crit.rb index ac339eb0b..cd3336e86 100644 --- a/lib/jwt/claims/crit.rb +++ b/lib/jwt/claims/crit.rb @@ -7,8 +7,10 @@ class Crit # Initializes a new Crit instance. # # @param expected_crits [String] the expected crit header values for the JWT token. - def initialize(expected_crits:) + # @param strict [Boolean] whether the crit header may contain only expected values. + def initialize(expected_crits:, strict: false) @expected_crits = Array(expected_crits) + @strict = strict end # Verifies the critical claim ('crit') in the JWT token header. @@ -24,12 +26,15 @@ def verify!(context:, **_args) missing = (expected_crits - context.header['crit']) raise(JWT::InvalidCritError, "Crit header missing expected values: #{missing.join(', ')}") if missing.any? + unexpected = (context.header['crit'] - expected_crits) + raise(JWT::InvalidCritError, "Unsupported critical headers: #{unexpected.join(', ')}") if strict && unexpected.any? + nil end private - attr_reader :expected_crits + attr_reader :expected_crits, :strict end end end diff --git a/lib/jwt/encoded_token.rb b/lib/jwt/encoded_token.rb index 214981df6..fa2017a74 100644 --- a/lib/jwt/encoded_token.rb +++ b/lib/jwt/encoded_token.rb @@ -190,7 +190,7 @@ def decode_payload raise JWT::DecodeError, 'Encoded payload is empty' if encoded_payload == '' if unencoded_payload? - verify_claims!(crit: ['b64']) + Claims::Crit.new(expected_crits: ['b64'], strict: true).verify!(context: ClaimsContext.new(self)) return parse_unencoded(encoded_payload) end