CVE-2026-33322:OIDC JWT 算法混淆

OIDC verifier 混用 client secret 与 JWKS key,最终通过恢复 JWKS-only 非对称验证关闭算法混淆。

状态: 已发布
首个包含版本: RELEASE.2026-04-17T00-00-00Z
影响入口: AssumeRoleWithWebIdentityAssumeRoleWithClientGrants
GitHub Issue: pgsty/minio#22

旧实现把 OIDC client secret 放进 JWT verifier keyring,同时允许 HMAC signing method。知道 client secret 的攻击者因此可以自行签发 HS token,再通过 STS 换取临时权限。最终修复恢复了 JWKS-only 非对称验证:宁可明确打破 HS256/384/512 兼容,也不保留一个会重新混淆信任语义的开关。

漏洞不在“有没有验签”

表面上看,旧代码确实执行了 JWT signature verification。真正失效的边界是:verifier 接受了哪一种 key,以及 token header 是否能选择与该 key 不匹配的算法语义。

攻击链需要满足几个条件:

  • 攻击者获得 OIDC client secret;
  • 攻击者构造 HMAC-signed ID token;
  • verifier 把 client secret 当作 HMAC signing key;
  • token 进入 WebIdentity 或 ClientGrants STS flow,换取临时凭据。

client secret 泄露本身当然严重,但它原本不应该自动获得“签发任意用户 ID Token”的权限。把两种能力混在同一个 keyring 中,才是算法混淆的核心。

兼容路径写出来了,又被主动删除

修复过程中曾经实现过 allow_hmac 一类兼容路径。它看起来很合理:默认安全,确有需要的用户可以显式打开。但继续把 shared secret 放进通用 verifier keyring,意味着管理员需要理解这个配置实际上扩大了整个 STS 信任边界;未来 method allowlist 只要发生漂移,漏洞就可能重现。

几种方案的取舍最终非常清楚:

方案收益风险结论
保留 secret keyring,只限制部分算法改动小,兼容 HMAC IdPkeyring 仍混合两种信任语义否决
增加 allow_hmac 配置兼容性显式配置本身难以正确理解,测试面扩大实现后回滚
JWKS-only边界清晰,刷新与重试共用同一 parserHS 用户必须迁移接受

这次最重要的决策不是“新增了哪些代码”,而是主动删除了已经完成的兼容实现。

最终不变量

修复集中在 OIDC JWT 验证路径,并固定了四条规则:

  • verifier key 只来自 IdP JWKS;
  • OIDC client secret 不进入 JWT verification keyring;
  • HS256、HS384、HS512 一律拒绝;
  • 正常 RS256 流程以及 JWKS refresh/retry 使用同一 method allowlist。

修复没有借 CVE 顺手扩展 JOSE 功能。PS256 与 EdDSA 不在这次事件的支持范围内。

验证与发布

开发记录包含 HS256 rejection、RS256 acceptance、JWKS refresh/retry regression tests,以及 focused go test ./internal/config/identity/openid。临时兼容 helper、配置与测试在最终 diff 中全部删除。

公开发布 lineage 中的修复提交为 f1f2239,并随 SILO 2026-04-17 发布。这篇文章记录历史验证,不代表本次博客整理重新执行了测试。

兼容性代价

这是明确的 breaking change。仍签发 HS256/384/512 token 的 IdP 必须先迁移到 JWKS-backed RSA/ECDSA,再升级 SILO。这里选择的是更窄、更容易解释的信任模型,而不是让旧配置继续工作。

最后修改 August 2, 2026: init commit (8338d5b)