Skip to content

test(web): cover same-origin checks on kit and collection writes - #159

Merged
mrgoonie merged 2 commits into
mainfrom
claude/modest-wozniak-wr2bof
Oct 29, 2026
Merged

mrgoonie merged 2 commits into
mainfrom
claude/modest-wozniak-wr2bof

Conversation

@mrgoonie

Copy link
Copy Markdown
Contributor

Closes #113.

Summary

The production check this issue asks for already landed in #103: resolveLimitedScopedActor (apps/web/app/lib/releases/release-state-http.ts) refuses a foreign Origin / non-same-origin Sec-Fetch-Site with 403 cross_origin whenever neither Authorization nor X-Admin-Secret is present (the session-cookie path). Both serveKit (kit-http.ts) and serveCollection (collection-http.ts, via resolveLimitedActor) call it for every non-GET request, because their routers classify access by HTTP method. What was missing was test coverage per route group, which this PR adds:

  • apps/web/tests/collections/collections-origin.test.ts (new): a foreign Origin, a sibling subdomain or Sec-Fetch-Site: same-site is 403 cross_origin on create, PATCH, DELETE, revisions, members and clone, and nothing is written. Same-origin, header-less and API-key-with-foreign-Origin writes pass.
  • apps/web/tests/personal-kits/kit-origin.test.ts (new): the existing kit origin case moved here (to keep kit-revisions.test.ts under the 200-LOC cap), plus every write sub-route (proposals, proposals/validate, preview-update, activate, rollback, rebase, conflicts/:id/resolve, revisions/:id/{reject,review,quarantine}) is 403 cross_origin, and header-less session and API-key writes pass.

No production code changes.

Verification

  • pnpm typecheck: passes.
  • npx vitest run (full suite): 142 files, 2687 passed, 3 skipped.
  • Isolated-context code review: it confirmed that every cookie-authenticated kit and collection write goes through the check. It also mutation-tested the new files: with crossOriginRefusal mocked to null, the "refuses" tests fail (expected 201 to be 403). I applied its low-severity suggestions (status assertions, per-sub-route coverage).

Docs impact

None. CLAUDE.md ("Same-origin on cookie mutations"), docs/api-reference.md#collections and docs/personal-kits-api.md already document 403 cross_origin for these routes.


Generated by Claude Code

The session path of kit and collection writes already refuses a foreign
Origin through resolveLimitedScopedActor. Pin it per route group: a foreign
Origin or same-site fetch is 403 cross_origin and writes nothing, while
same-origin, header-less and API-key writes pass. Collections also cover
PATCH and DELETE. Kit origin cases move to their own file to keep
kit-revisions under 200 lines.

Closes #113

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YPFjLezDdYaFNQwfYGjQvq
…-route

Assert status and error code for every collection and kit write route,
so a write later classified as a read cannot drop the check silently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YPFjLezDdYaFNQwfYGjQvq
@mrgoonie
mrgoonie merged commit 25dabca into main Oct 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(web): same-origin check on cookie-authenticated kit and collection writes

2 participants