koala73 / koala73/worldmonitor
security(auth): consider binding Clerk azp in validateBearerToken
- Dominant language
- TypeScript
- Stars
- 86.6k
- Forks
- 13.1k
- Avg merge
- 8h 4m
- Merged PRs (30d)
- 825
Description
## Why
`server/auth-session.ts` `validateBearerToken` verifies issuer, signature, expiry, and audience when present. It never reads `azp`. No caller does. Clerk sets `azp` to the origin that minted a browser session token and recommends checking it against authorized parties.
Probe on 2026-09-15 against `api/internal/mcp-grant-mint.ts` with the real `resolveClerkSession`, remote JWKS, and grant HMAC: a bearer with a foreign `azp` and a foreign `Origin` header mints a grant (200, one Redis write). Cookie-only, wrong-key, wrong-issuer, and expired tokens all return 401 with no write.
## Why not now
Minting needs a JWT for the victim's `sub`. No origin that can obtain one has been shown. The only hosts under `worldmonitor.app` outside the app are `clerk.` (the identity provider) and `abacus.` (self-hosted Umami on our own infrastructure). Binding `azp` on one handler protects nothing that the gateway and Convex do not also accept.
## If it is done
1. Do it once in `validateBearerToken`, not per handler.
2. Fail open when `azp` is absent. Clerk omits it on non-browser tokens.
3. Survey what `azp` desktop (`tauri://localhost`), preview (`worldmonitor-*-eliewm.vercel.app`), and the subdomain hosts carry before choosing the allowlist. Seed it from `TRUSTED_RETURN_URL_ORIGINS`.
Found during the 2026-09-15 security-validation batch (McpGrantMintOriginUnbound outcome, closed no-change).
Contributor guide
Research direction
Start in server/auth-session.ts at validateBearerToken and inspect how TRUSTED_RETURN_URL_ORIGINS is used. Survey the azp values carried by desktop, preview, and subdomain hosts before deciding the allowlist. Done means azp is checked once there, absent azp remains accepted, and the relevant token validation behavior is covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- authentication, backend, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100