Commit 5038144
fix(security): bind UCAN JWT verification to the iss key, not the kid header
UCAN.fromJWT verified the EdDSA signature against the public key named in the
attacker-controlled `kid` header, then trusted the `iss` claim without checking
the two agree. An attacker could sign a token with their own key, place that key
in `kid`, and claim any `iss` (e.g. a trusted root) — an issuer-spoofing
authorization bypass. The forged token passed validateJWT / parseTransportUCANs,
and via UCANValidator.capabilitiesFor(..., issuer=root) yielded capabilities
attributed to the root. Reachable from transport input (e.g. DlfsMcpTools).
Fix: derive the verification key from the `iss` DID (did:key encodes the issuer
key) and verify against it; the `kid` header is no longer trusted for key
selection. Legitimately signed tokens are unaffected (kid == iss key already).
The CAD3 path (UCAN.verifySignature / validate) was already correct.
Audit of the other JWT verification paths:
- PeerAuth.verifySelfIssued: safe — binds sub to the signing key (sub == did:key(kid))
- PeerAuth.verifyPeerSigned / OAuthService (JWKS RS256) / JWKSKeys: safe
Added a SECURITY WARNING to the kid-trusting JWT.verifyEdDSA()/verifyPublic(jwt).
Adversarial tests (UCANTest): forge iss=ROOT signed by a rogue key and assert
rejection at fromJWT, validateJWT, the transport boundary, and in a proof chain;
plus a regression that genuine tokens still verify. Confirmed all four fail
against the pre-fix kid-based verification.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent ec3ffac commit 5038144
3 files changed
Lines changed: 106 additions & 11 deletions
File tree
- convex-core/src
- main/java/convex/auth
- jwt
- ucan
- test/java/convex/auth/ucan
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
141 | 141 | | |
142 | 142 | | |
143 | 143 | | |
144 | | - | |
145 | | - | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
146 | 154 | | |
147 | 155 | | |
148 | 156 | | |
| |||
374 | 382 | | |
375 | 383 | | |
376 | 384 | | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
377 | 391 | | |
378 | 392 | | |
379 | 393 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
398 | 398 | | |
399 | 399 | | |
400 | 400 | | |
401 | | - | |
402 | | - | |
403 | | - | |
404 | 401 | | |
405 | 402 | | |
406 | 403 | | |
407 | | - | |
408 | | - | |
409 | | - | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
410 | 413 | | |
| 414 | + | |
411 | 415 | | |
412 | | - | |
413 | | - | |
414 | | - | |
| 416 | + | |
| 417 | + | |
415 | 418 | | |
416 | 419 | | |
417 | 420 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
454 | 455 | | |
455 | 456 | | |
456 | 457 | | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
457 | 535 | | |
458 | 536 | | |
459 | 537 | | |
| |||
0 commit comments