security: eliminate OAUTH_STATE_SECRET fallback + fix ASSETS binding#62
security: eliminate OAUTH_STATE_SECRET fallback + fix ASSETS binding#62chitcommit merged 1 commit intomainfrom
Conversation
Remove hardcoded 'default-secret-change-in-production' fallback from all OAuth routes (wave.ts, google.ts, oauth-state.ts). Routes now return 503 when OAUTH_STATE_SECRET is not configured, preventing CSRF bypass. Secret deployed to all 3 Cloudflare Workers environments (default, staging, production). Also fix ASSETS binding in both wrangler.toml files — missing `binding = "ASSETS"` key caused c.env.ASSETS.fetch() to crash on static asset requests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@coderabbitai review Please evaluate:
|
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughThe changes enforce OAuth CSRF protection by requiring explicit Changes
Possibly related PRs
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
chittyfinance | 7accf78 | Mar 25 2026, 04:37 AM |
PR Review: security: eliminate OAUTH_STATE_SECRET fallback + fix ASSETS bindingThis is a solid, high-priority security fix. The core changes are correct and well-scoped. A few things to call out: ✅ What's goodCSRF fix is correct and necessary. The
503 error messaging is descriptive.
|
There was a problem hiding this comment.
Pull request overview
This PR hardens OAuth CSRF protections by removing insecure OAUTH_STATE_SECRET fallbacks and ensures Cloudflare static asset requests don’t crash by correctly binding ASSETS in Wrangler configs.
Changes:
- Remove
default-secret-change-in-productionfallbacks and fail closed whenOAUTH_STATE_SECRETis not configured (Wave + Google OAuth routes; Node oauth-state helper). - Add
[assets] binding = "ASSETS"to Wrangler configs to supportc.env.ASSETS.fetch()for static asset serving. - Use constant-time signature verification in the edge OAuth state validator via
tokenEqual().
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| wrangler.toml | Binds static assets to ASSETS Fetcher for worker runtime. |
| deploy/system-wrangler.toml | Mirrors the ASSETS binding and documents OAUTH_STATE_SECRET as required for OAuth flows. |
| server/routes/wave.ts | Removes secret fallback; returns 503/redirects when OAuth state secret is missing. |
| server/routes/google.ts | Removes secret fallback; returns 503/redirects when OAuth state secret is missing. |
| server/lib/password.ts | Refactors tokenEqual() to reuse the existing constant-time string comparator. |
| server/lib/oauth-state.ts | Removes fallback secret; adds explicit failure behavior when secret is unset. |
| server/lib/oauth-state-edge.ts | Switches signature verification to tokenEqual() for timing-safe comparison. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export function validateOAuthState(state: string): OAuthStateData | null { | ||
| if (!STATE_TOKEN_SECRET) { | ||
| console.error('OAUTH_STATE_SECRET is required for OAuth validation'); | ||
| return null; | ||
| } |
There was a problem hiding this comment.
validateOAuthState() still verifies the HMAC with a direct string comparison (signature !== expectedSignature). That’s not timing-safe and can leak information about the expected signature over many requests. Since this module is used by the Express routes, consider switching to a constant‑time compare (e.g., using the existing tokenEqual() helper or Node’s crypto.timingSafeEqual on decoded bytes).
Summary
'default-secret-change-in-production'fallbacks from OAuth routes (wave.ts,google.ts,oauth-state.ts). Routes now return 503 whenOAUTH_STATE_SECRETis not configured, preventing CSRF bypass in production.binding = "ASSETS"to[assets]block in bothwrangler.tomlanddeploy/system-wrangler.toml— fixesc.env.ASSETS.fetch()crash on static asset requests.OAUTH_STATE_SECRETset viawrangler secret putfor default, staging, and production environments.oauth-state-edge.tsnow usestokenEqual()for constant-time signature verification.Audit context
Items 4 and 38 from the credential alignment audit (2026-03-25). Both were classified as Immediate priority — active security/availability vulnerabilities in production.
Test plan
npx tsc --noEmitpasses (verified locally)/authorizereturns 503 without secret (correct)/authorizereturns 503 without secret (correct)finance.chitty.ccafter deploydefault-secret-changestrings in codebase (verified via grep)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
OAUTH_STATE_SECRETenvironment variable; missing configuration returns appropriate error responses (503 for authorization, error redirect for callback).Bug Fixes
Chores