fix(auth): tighten public auth surface — CORS + rate limit (Brief 4 of fix-auth-bypass) #9
No reviewers
Labels
No labels
agent-context-drift
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: rstillwell/deckhearth#9
Loading…
Reference in a new issue
No description provided.
Delete branch "brief/fix-auth-bypass/4-tighten-auth-surface"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Convoy
fix-auth-bypass/ Brief 4 of 5. Adds rate limiting to/api/auth/loginand/api/auth/register(5/15min per IP) and removes their wide-open CORS allowlist. See.convoys/fix-auth-bypass.mdfor the full convoy plan.Rate limiting
lib/rate-limit.js— lazy singleton, single source of truth, 5 attempts per 15-minute sliding window per IP, key prefixtcgvault:auth.@upstash/ratelimit@^2.0.8+@upstash/redis@^1.38.0.KV_REST_API_URL/KV_REST_API_TOKEN(Vercel Upstash Marketplace convention — auto-provisioned, no manual env-var setup needed).console.warn, returns{ allowed: true, remaining: Infinity, reset: 0 }.x-forwarded-forfirst hop, withreq.socket.remoteAddressfallback. NOTreq.body.email(rotates) orAuthorizationheader (absent on unauthenticated login).Retry-Afterheader (seconds until reset) when rate-limited.CORS
Access-Control-Allow-Origin: *+ companion headers +OPTIONSpreflight fromlogin.jsandregister.js. These are first-party endpoints called from the same-origin SPA; the*allowlist was a dev convenience that shipped to prod.verify.jsCORS is out of scope per architect'scors-tightendeferral (see convoy plan § Architect's calls). Will land in a futurecors-tightenconvoy.Files changed
package.json— added@upstash/ratelimit@^2.0.8and@upstash/redis@^1.38.0to dependencies (alphabetical)package-lock.json— regenerated vianpm installlib/rate-limit.js(new, ~70 lines)pages/api/auth/login.js— removed CORS block + OPTIONS preflight; added rate-limit check after method gatepages/api/auth/register.js— same treatment as loginNet diff: 5 files, +126 / −22 LOC.
Test plan
npm run buildexits 0npm run lintmatches baseline (128 problems / 81 errors / 47 warnings); zero new lint issuesnpm ls @upstash/ratelimitreports single2.0.x;npm ls @upstash/redisreports single1.38.xKV_REST_API_URLandKV_REST_API_TOKENconsole.warn, returns{ allowed: true, remaining: Infinity, reset: 0 }grep -E "Access-Control-Allow-Origin" pages/api/auth/login.js pages/api/auth/register.jsreturns zero hitsgrep -E "Access-Control-Allow-Origin" pages/api/auth/verify.jsstill returns hits (correctly out of scope percors-tightendeferral)Retry-AfterheaderOPTIONS /api/auth/loginshould now return 405 (Method not allowed) instead of 200 (since we removed the preflight handler — this is correct for a same-origin endpoint)⚠️ Pre-merge requirements
Vercel env vars (auto-provisioned by Upstash Marketplace integration):
KV_REST_API_URL✅ provisionedKV_REST_API_TOKEN✅ provisionedConfirmed live by maintainer (2026-05-23) — Upstash database created via Vercel Marketplace. No manual env-var setup required.
Other Vercel-injected vars (not used, listed for reference):
KV_REST_API_READ_ONLY_TOKEN(read-only, not needed for rate-limit writes)KV_URL(Vercel KV-native, not used by@upstash/redisREST client)REDIS_URL(TCP, not used by@upstash/redisREST client)If the env vars are NOT set in a production deploy, the first auth call will return 500 (fail-closed by design — see R8 in the convoy plan).
⚠️ Brief deviation from literal text
The brief specified env var names
UPSTASH_REDIS_REST_URL/UPSTASH_REDIS_REST_TOKEN(the upstream Upstash convention). Mid-implementation we discovered the user provisioned Upstash via Vercel Marketplace, which usesKV_REST_API_*names. This PR uses theKV_REST_API_*names per Upstash's official Vercel integration guide and to eliminate manual env-var aliasing. The convoy brief onconvoy/fix-auth-bypasswill be updated to match by the doc-writer pass at end of convoy.Out of scope (intentionally — see convoy plan)
pages/api/auth/verify.js→cors-tightenconvoy (architect's call)/api/cards/import-*,/api/admin/*) →add-rate-limitingconvoyAudit cohort
Reviewer dispatch follows post-push. No UI surface → design-system + a11y + browser-smoke auditors do not run.
🤖 Pipeline metadata: convoy=fix-auth-bypass, brief=4, depends_on=[1], audit=reviewer-only
Made with Cursor
The latest updates on your projects. Learn more about Vercel for GitHub.
Pipeline Health
Build + CI gates
Build runs on Vercel; this CI runs lint and schema-map drift only (no duplicate build).
Role reports
See individual comments above for details. This rollup updates automatically.