Repository navigation
Move authserver JWK parsing to go-jose v4 - #7012
Conversation
go-jose v3 validates RSA keys embedded in JWKs without bounding their size (GHSA-mgcc-cww5-fp2q) and has no patched release. Parse keys with go-jose v4.1.6 everywhere ToolHive owns the parsing, copying parsed keys field by field into the v3 types fosite v0.49.0 still requires. fosite itself parses client assertions and OIDC request objects with v3 before looking up a client, so refuse any such JWT whose header embeds a jwk, or that is not a compact JWS, before fosite sees it. fosite never uses an embedded key, so conforming clients are unaffected. Raise go-jose's new 4096-bit RSA parse limit to our existing 8192-bit policy so registered clients keep loading, and decode a stored Redis key set separately so one that go-jose rejects still answers invalid_client instead of failing the whole row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Malformed request objects receive different responses for existing back-channel-only clients and unknown clients, leaking client existence and violating the client-hiding contract.
2 open issues
What changed in this PR
Moves auth-server JWK parsing to go-jose v4 to address GHSA-mgcc-cww5-fp2q, while retaining compatibility with fosite’s v3 interfaces.
Changes:
- Migrates client key parsing to v4 and adds field-by-field conversion for fosite.
- Guards client assertions and authorization request objects against embedded keys and non-compact serialization.
- Preserves the 8192-bit RSA limit and returns
invalid_clientfor stored JWKS that cannot be parsed.
| File | Description |
|---|---|
test/e2e/thv-operator/virtualmcp/virtualmcp_private_key_jwt_test.go |
Uses v4 keys in registration fixtures. |
pkg/oauthproto/dcr.go |
Uses v4 JWK types for registration requests. |
pkg/authserver/upstream/oidc_test.go |
Migrates token-signing fixtures to v4. |
pkg/authserver/storage/redis.go |
Separates JWKS decoding from stored-client decoding. |
pkg/authserver/storage/redis_test.go |
Tests valid and invalid stored-JWKS round trips. |
pkg/authserver/storage/memory_test.go |
Converts v4 test keys for fosite clients. |
pkg/authserver/storage/configured_stamp_test.go |
Updates configured-client key fixtures. |
pkg/authserver/storage/configured_client_reconcile_test.go |
Uses v4 keys in reconciliation tests. |
pkg/authserver/server/registration/dcr.go |
Converts fosite keys for v4 validation. |
pkg/authserver/server/registration/dcr_test.go |
Migrates registration test keys to v4. |
pkg/authserver/server/registration/configured_client.go |
Uses v4 configured-client key types. |
pkg/authserver/server/registration/client.go |
Converts v4 keys when constructing fosite clients. |
pkg/authserver/server/registration/client_test.go |
Adapts key assertions to the conversion boundary. |
pkg/authserver/server/provider.go |
Wraps client authentication with the JWS guard. |
pkg/authserver/server/handlers/dcr.go |
Uses v4 keys in the registration handler. |
pkg/authserver/server/handlers/dcr_test.go |
Updates registration-handler fixtures to v4. |
pkg/authserver/server/handlers/authorize.go |
Rejects unsafe authorization request objects. |
pkg/authserver/server/handlers/authorize_test.go |
Tests embedded-key rejection without redirects. |
pkg/authserver/server/fosite_jws_guard.go |
Adds checks before fosite parses untrusted JWS input. |
pkg/authserver/server/fosite_jws_guard_test.go |
Tests guard inputs and authentication delegation. |
pkg/authserver/server/crypto/keys.go |
Sets v4’s RSA parsing limit to 8192 bits. |
pkg/authserver/runner/embeddedauthserver.go |
Loads configured JWKS files with v4. |
pkg/authserver/runner/embeddedauthserver_test.go |
Updates configured-JWKS fixtures to v4. |
pkg/authserver/internal/fositejose/fositejose.go |
Adds field-by-field v3/v4 key conversion. |
pkg/authserver/integration_test.go |
Migrates private-key JWT registration fixtures. |
pkg/authserver/configured_client_runner_integration_test.go |
Writes configured-client JWKS using v4. |
pkg/authserver/config.go |
Uses v4 keys in auth-server configuration. |
pkg/authserver/config_test.go |
Updates configuration test keys to v4. |
docs/arch/11-auth-server-storage.md |
Documents JWS restrictions, errors, and logging. |
Review effort: Balanced
0a8d1ee to
6cc13a3
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7012 +/- ##
==========================================
+ Coverage 80.43% 80.44% +0.01%
==========================================
Files 850 852 +2
Lines 86943 87035 +92
==========================================
+ Hits 69932 70016 +84
- Misses 17006 17014 +8
Partials 5 5 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Rejecting an unsafe request object after the back-channel-only client check answered differently for configured and unknown clients, which revealed whether a back-channel client exists. The check does not depend on the client, so it now runs first. Also pin that go-jose's RSA parse limit matches MaxRSAKeyBits, so client keys above go-jose's 4096-bit default keep decoding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jhrozek
left a comment
There was a problem hiding this comment.
Thanks, this looks good. I'll send a follow-up PR on top of it for a few things we found in review, including a case where the authorize request-object check can be skipped when the query string doesn't parse cleanly, and accepting padded base64url in JWKS the way go-jose v3 did.

Summary
go-jose v3 is affected by GHSA-mgcc-cww5-fp2q and has no patched release. This moves the auth server's JSON Web Key handling to go-jose v4.
pkg/authserver/internal/fositejose).client_assertionvalues and authorizationrequestobjects whose JWS header embeds ajwk, or that are not compact-serialized.invalid_clientrather than a storage error.Type of change
Test plan
task test)task lint-fix)Does this introduce a user-facing change?
Yes.
client_assertionorrequestobject with an embeddedjwkheader was accepted, and the embedded key was ignored.invalid_clientorinvalid_request_object, and the rejection is logged at WARN. Clients that sign with their registered key are unaffected.Special notes for reviewers
fositejoseconversion package and the embedded-jwkguard (fosite_jws_guard.go). Both can be removed once fosite moves to go-jose v4, and comments in the code say so.jose.MaxRSAModulusBitsis a process-wide variable. Setting it to 8192 also applies to other go-jose v4 users in the same binary, whose default would otherwise be 4096.🤖 Generated with Claude Code