Skip to content

fix(security): pin the JWT algorithm allowlist in compatibility mode#1298

Merged
dunglas merged 1 commit into
mainfrom
fix/jwt-alg-allowlist-compat
Jul 18, 2026
Merged

fix(security): pin the JWT algorithm allowlist in compatibility mode#1298
dunglas merged 1 commit into
mainfrom
fix/jwt-alg-allowlist-compat

Conversation

@dunglas

@dunglas dunglas commented Jul 18, 2026

Copy link
Copy Markdown
Owner

From the 1.0 auth-surface security review.

Problem

applyModernDefaults (hub.go) returned early whenever a protocol-version compatibility was configured, before assigning the default asymmetric-only JWS algorithm allowlist. A hub built with a bare key function (the JWKS path, WithPublisher/SubscriberJWTKeyFunc) and no explicit algorithms therefore left the allowlist empty in compatibility mode, so jwtParserOptions never applied jwt.WithValidMethods. The parser then accepted whatever alg the token header declared.

Failure scenario: an operator on compatibility mode (v7/v8) wiring a JWKS keyfunc that returns a parsed public key, with no explicit algorithms — an attacker forges an HS256 token signed with the RSA/EC public-key bytes as the HMAC secret. Not exploitable against the built-in WithPublisherJWT/WithSubscriberJWT configs (they always set algs=[alg]) or a keyfunc that pins t.Method; it bites the bare-JWKS-in-compat-mode path.

Fix

Apply the asymmetric-only default allowlist to every configured key function in all modes; a relaxed protocol version must not relax the signature-algorithm check. Operators pinning a symmetric algorithm on a bare key function still opt in explicitly via WithPublisher/SubscriberJWTAlgorithms.

Added TestCompatModeDefaultJWTAlgorithms: a compat-mode hub with a bare HMAC keyfunc now rejects an HS256 token at parse time.

Not changed

The review also flagged the per-detail actions array as having no explicit element cap (INFO). The loop is O(n), bounded by the transport request-body limit, with no compilation or amplification, and maxMercureDetails/maxDetailTopics remain enforced. No change warranted.

Tests pass with -race on both tag combos; go vet and golangci-lint clean.

Copilot AI review requested due to automatic review settings July 18, 2026 09:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

applyModernDefaults returned before assigning the default asymmetric-only
algorithm allowlist whenever a protocol-version compatibility was set. A hub
built with a bare key function (the JWKS path) and no explicit algorithms then
let the parser accept whatever alg the token header declared, so a token forged
as HS256 against an RSA/EC public key could be presented for algorithm
confusion. Apply the allowlist in every mode; a relaxed protocol version must
not relax the signature-algorithm check. Operators pinning a symmetric
algorithm on a bare key function still opt in via WithPublisher/SubscriberJWTAlgorithms.
@dunglas
dunglas force-pushed the fix/jwt-alg-allowlist-compat branch from 4cf5d85 to e944c0b Compare July 18, 2026 09:46
Copilot AI review requested due to automatic review settings July 18, 2026 09:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@dunglas
dunglas merged commit 620ed98 into main Jul 18, 2026
43 checks passed
@dunglas
dunglas deleted the fix/jwt-alg-allowlist-compat branch July 18, 2026 10:17
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