fix(auth): remove dead challenge/response surface (security findings 8+16)#3229
fix(auth): remove dead challenge/response surface (security findings 8+16)#3229frdomovic wants to merge 3 commits into
Conversation
…8+16) The GET /auth/challenge endpoint minted a signed nonce+jti that nothing ever stored or consumed, and TokenManager::verify_challenge had zero callers - the surface was decorative. Since user_password is the only shipped provider (no NEAR-wallet login this iteration), remove the dead surface instead of building a nonce store: - drop TokenManager::generate_challenge / verify_challenge and ChallengeClaims - drop the /challenge route, challenge_handler, and ChallengeResponse - drop SecretType::JwtChallenge, its storage keys, rotation/initialize entries, and get_jwt_challenge_secret; legacy system:secrets:jwt_challenge* entries in storage are simply never read again - update operator/contributor docs that described the challenge flow TEE/KMS attestation challenges (crates/merod/src/kms) and the unrelated NodeChallenge admin DTOs are untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🤖 MeroReviewer
Reviewed by 2 agents | Quality score: 90% | Review time: 190.4s
✅ No Issues Found
All agents reviewed the code and found no issues. LGTM! 🎉
🤖 Generated by MeroReviewer | Review ID: review-8292737c
Documentation ReviewThe following documentation may need updates based on the changes in this PR:
|
There was a problem hiding this comment.
🤖 AI Code Reviewer
Reviewed by 2 agents | Quality score: 90% | Review time: 834.1s
✅ No Issues Found
All agents reviewed the code and found no issues. LGTM! 🎉
🤖 Generated by AI Code Reviewer | Review ID: review-aa980757
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
Security finding
[M] Challenge/response has no replay protection / is decorative (security-review items 8 + 16) —
crates/auth/src/auth/token/jwt.rs.GET /auth/challengemints a randomnonce+jti, but nothing ever stores them andverify_challengehas zero callers — a signed challenge is never demanded by any login flow. The surface is security theater: it suggests proof-of-possession that doesn't exist, and any real fix (a single-use nonce store consumed by a wallet provider's token exchange) would be dead machinery, since core ships no wallet provider — plus a naively-persisted nonce per unauthenticatedGETis a storage-write DoS vector.Decision (team): no NEAR/wallet login this iteration —
user_passwordis the only provider, and password auth needs no PoP step. Remove the dead surface instead of building a nonce store for a provider that doesn't exist.Before → after
GET /auth/challengeTokenManagergenerate_challenge/verify_challenge(dead) +ChallengeClaims.JwtChallenge, rotated forever for nothing.JwtAuth+Csrfonly. Legacysystem:secrets:jwt_challenge*storage entries are simply never read again (doc-commented onSecretType).operate/auth.mdxet al. describe challenge lifetime / wallet challenge auth.Deliberately kept: the TEE/KMS attestation challenge flow (
crates/merod/src/kms) and libp2p/sync uses of the word — unrelated subsystems.NodeChallengeDTOs incalimero-server-primitivesare unrouted legacy public API — candidate for a separate dead-code sweep.How to test
Manual:
curl http://<node>/auth/challenge→ 404; user-password login and token refresh unaffected.Client follow-ups (separate PRs, non-breaking today since no server ever advertises a wallet provider)
getChallenge()(src/auth-api/auth-client.ts:86),ChallengeResponsetype, and the MSW mock — breaking API change for the package, needs a version bump.near_walletchallenge→sign→token branch inLoginView.tsx:277-340+ mocks/fixtures.Related: #3079/#3080/#3081/#3082/#3083 (the auth security-review stack). Expect a trivial textual conflict with #3083 in
jwt.rs/secrets.rs— whichever merges second rebases.