fix(auth): require CSRF validation for cookie mutations - #615
Merged
IvGolovach merged 1 commit intoJun 4, 2026
Merged
Conversation
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
There was a problem hiding this comment.
1 issue found across 11 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
IvGolovach
force-pushed
the
codex/csrf-cookie-mutation-routes
branch
from
May 27, 2026 17:03
b554831 to
c72e285
Compare
IvGolovach
force-pushed
the
codex/csrf-cookie-mutation-routes
branch
from
May 30, 2026 22:50
c72e285 to
aa08dfa
Compare
Validation * Validation tier: Tier 3 - security-sensitive auth mutation behavior. * git diff --check: PASS * git diff --cached --check: PASS * bun --cwd packages/frontend test __tests__/api/settingsTokensDelete.test.ts: PASS, 6 tests passed * bun --cwd packages/frontend test __tests__/api/settingsTokensList.test.ts __tests__/api/settingsTokensDelete.test.ts __tests__/api/settingsSubmittedDataDelete.test.ts __tests__/api/deviceAuthorizeCsrf.test.ts __tests__/api/settingsDeviceRenameCsrf.test.ts __tests__/lib/requestSessionCsrf.test.ts: PASS, 37 tests passed * Ledger: not applicable - not required for selected validation tier/change family. * Version: not applicable - not required for selected validation tier/change family. * Not run: full frontend test suite - not required locally because targeted API and auth CSRF tests cover the changed routes. Rollback * git revert HEAD
IvGolovach
force-pushed
the
codex/csrf-cookie-mutation-routes
branch
from
May 31, 2026 22:37
aa08dfa to
f5b4d9a
Compare
junhoyeo
added a commit
that referenced
this pull request
Jul 6, 2026
… modernize cache invalidation Review follow-up after merging main into this branch. Main moved on while this PR was open, so DELETE /api/settings/account is brought up to the current baseline: - Authenticate via getSessionFromRequest(request) instead of bare getSession(), inheriting the CSRF Origin-allowlist gate that #615 (f2bf654) retrofitted onto every other cookie-mutating settings route (submitted-data, devices, tokens). - Use normalizeUsernameCacheKey() for all user:/user-rank:/embed-user: revalidateTag calls and revalidateUsernamePaths() for path revalidation, matching the post-#485 baseline. - Call revalidateUserGroupLeaderboards() (#524) before the users-row delete, since the helper needs the group membership rows that the delete cascades away. Best-effort like all other revalidation. - Update the route tests for the request-based signature: requests now carry an Origin header exercised against the real getSessionFromRequest, plus new cases asserting missing/disallowed Origin yields 401 with no DB delete, mirroring the sibling routes' CSRF tests. Constraint: Cookie-auth mutations must pass the Origin allowlist convention adopted in #615 Constraint: revalidateUserGroupLeaderboards reads group membership rows that ON DELETE CASCADE removes Rejected: Bearer personal-token path for account deletion | web-Settings-UI action; session-only is the conservative default and answers the parity question raised in review Rejected: Invalidate group leaderboards after the delete | membership rows are already cascaded away by then Confidence: high Scope-risk: narrow Not-tested: CSRF_ALLOWED_ORIGINS env override branch (covered indirectly by requestSession's own tests)
junhoyeo
added a commit
that referenced
this pull request
Jul 6, 2026
…letion (#379) * feat(settings): add Danger Zone with self-service data and account deletion Add a Danger Zone section to the Settings page with two destructive actions: - Delete submitted data: removes leaderboard entries, profile stats, and usage history while keeping the account active - Delete account: permanently deletes the user and all associated data (sessions, tokens, submissions) via ON DELETE CASCADE Both flows use a 3-step confirmation modal (intent → warning → typed confirmation) matching the CLI's triple-confirmation pattern. New API route: DELETE /api/settings/account New tests: settingsAccountDelete.test.ts (5 cases) * Update packages/frontend/src/app/settings/SettingsClient.tsx Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(settings): gate account deletion behind CSRF Origin allowlist and modernize cache invalidation Review follow-up after merging main into this branch. Main moved on while this PR was open, so DELETE /api/settings/account is brought up to the current baseline: - Authenticate via getSessionFromRequest(request) instead of bare getSession(), inheriting the CSRF Origin-allowlist gate that #615 (f2bf654) retrofitted onto every other cookie-mutating settings route (submitted-data, devices, tokens). - Use normalizeUsernameCacheKey() for all user:/user-rank:/embed-user: revalidateTag calls and revalidateUsernamePaths() for path revalidation, matching the post-#485 baseline. - Call revalidateUserGroupLeaderboards() (#524) before the users-row delete, since the helper needs the group membership rows that the delete cascades away. Best-effort like all other revalidation. - Update the route tests for the request-based signature: requests now carry an Origin header exercised against the real getSessionFromRequest, plus new cases asserting missing/disallowed Origin yields 401 with no DB delete, mirroring the sibling routes' CSRF tests. Constraint: Cookie-auth mutations must pass the Origin allowlist convention adopted in #615 Constraint: revalidateUserGroupLeaderboards reads group membership rows that ON DELETE CASCADE removes Rejected: Bearer personal-token path for account deletion | web-Settings-UI action; session-only is the conservative default and answers the parity question raised in review Rejected: Invalidate group leaderboards after the delete | membership rows are already cascaded away by then Confidence: high Scope-risk: narrow Not-tested: CSRF_ALLOWED_ORIGINS env override branch (covered indirectly by requestSession's own tests) --------- Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Originallowlist gate before using the browser session.Authorizationheaders bypass browser CSRF checks on settings routes.Why
Several browser-facing mutation routes were using cookie session helpers directly or accepted
Authorizationheaders through the shared request-session helper. That made the CSRF boundary inconsistent across settings and device routes. This change centralizes request-session handling so cookie-authenticated mutations require a trustedOrigin, while non-browser Bearer-token flows remain explicit and intentional.Diff scope
packages/frontend/src/lib/auth/requestSession.ts: adds an option to disableAuthorizationheader session resolution for routes that should only use cookie sessions behind the CSRF gate.Origin, and rejectedAuthorization-header session-auth cases for the changed mutation routes.Branch integrity
main715fddf6db88258c50eb20a5cc8d698e442f35b90 behind / 1 ahead715fddf6db88258c50eb20a5cc8d698e442f35b9Commit integrity
c72e2859ba471055ef86e992cdb58bc71c204080 fix(auth): apply CSRF gate to cookie mutationsDiff hygiene
git diff --name-status origin/main...HEAD: expected route/helper/test files only.git diff --check origin/main...HEAD: PASS, no output..envfiles, credentials, local environment files, caches, build outputs, or unrelated generated files are included.Validation mode and proof
bun --cwd packages/frontend test __tests__/api/settingsTokensDelete.test.ts: PASS, 6 tests passed.bun --cwd packages/frontend test __tests__/api/settingsTokensList.test.ts __tests__/api/settingsTokensDelete.test.ts __tests__/api/settingsSubmittedDataDelete.test.ts __tests__/api/deviceAuthorizeCsrf.test.ts __tests__/api/settingsDeviceRenameCsrf.test.ts __tests__/lib/requestSessionCsrf.test.ts: PASS, 37 tests passed.git diff --check origin/main...HEAD: PASS, no output.CI context confirmation
Runtime safety
Documentation integrity
Rollback plan
Known residual risks