CVE-2026-33322: OIDC JWT Algorithm Confusion

The OIDC verifier mixed a client secret with JWKS keys; restoring asymmetric, JWKS-only verification closed the algorithm-confusion path.

Status: Released
First containing release: RELEASE.2026-04-17T00-00-00Z
Affected entry points: AssumeRoleWithWebIdentity, AssumeRoleWithClientGrants
GitHub issue: pgsty/minio#22

The old implementation placed the OIDC client secret in the JWT verifier keyring while also accepting HMAC signing methods. An attacker who knew that client secret could therefore mint an HS-signed token and exchange it through STS for temporary credentials. The final fix restored asymmetric, JWKS-only verification. It deliberately broke HS256/384/512 compatibility instead of keeping an option that would reintroduce ambiguous trust semantics.

The vulnerability was not the absence of signature verification

At first glance, the old code did verify JWT signatures. The boundary that failed was more specific: which kind of key the verifier would accept, and whether the token header could select an algorithm with semantics that did not match that key’s intended role.

The attack chain required several conditions:

  • the attacker obtained the OIDC client secret;
  • the attacker constructed an HMAC-signed ID token;
  • the verifier treated the client secret as an HMAC signing key;
  • the token reached the WebIdentity or ClientGrants STS flow and was exchanged for temporary credentials.

Disclosure of a client secret is already serious, but it should not automatically confer the power to issue arbitrary user ID tokens. Combining those capabilities in one keyring created the algorithm-confusion vulnerability.

A compatibility path was implemented, then deliberately removed

During the fix, an allow_hmac-style compatibility path was implemented. It appeared reasonable: keep the secure default while letting users with a real requirement opt in. But retaining a shared secret in the general verifier keyring meant administrators would need to understand that the option expanded the entire STS trust boundary. Any future drift in the method allowlist could reopen the flaw.

The trade-off became clear:

OptionBenefitRiskDecision
Keep the secret keyring and restrict some algorithmsSmall change; preserves HMAC IdPsThe keyring still mixes two trust semanticsRejected
Add an allow_hmac optionMakes compatibility explicitThe option is difficult to reason about correctly and expands the test surfaceImplemented, then reverted
JWKS-only verificationClear boundary; refresh and retry use the same parserHS users must migrateAccepted

The most important decision was not what code was added, but that a completed compatibility implementation was removed.

Final invariants

The fix was concentrated in the OIDC JWT verification path and established four rules:

  • verifier keys come only from the identity provider’s JWKS;
  • the OIDC client secret never enters the JWT verification keyring;
  • HS256, HS384, and HS512 are always rejected;
  • the ordinary RS256 flow and JWKS refresh/retry use the same method allowlist.

The CVE was not used as a pretext for expanding JOSE support. PS256 and EdDSA remained out of scope.

Verification and release

The development record includes HS256 rejection, RS256 acceptance, JWKS refresh/retry regression tests, and focused go test ./internal/config/identity/openid. Temporary compatibility helpers, configuration, and tests were all removed from the final diff.

The public fix is f1f2239, released with SILO 2026-04-17. This article records the historical verification; those tests were not rerun while preparing the chronicle.

Compatibility cost

This is an explicit breaking change. Identity providers that still issue HS256/384/512 tokens must migrate to JWKS-backed RSA or ECDSA before upgrading SILO. The project chose a narrower trust model that is easier to explain and audit over preserving a configuration that happened to work before.

Last modified August 2, 2026: init commit (8338d5b)