Repository navigation
fix(security): drop wildcard CORS and reject cross-site tRPC POSTs - #21
Merged
Merged
Conversation
Remove the starter-kit Access-Control-Allow-Origin: * headers and OPTIONS handler from /api/trpc; the app is same-origin only. Reject state-changing requests whose Sec-Fetch-Site is not same-origin/none, closing the CSRF gap that SameSite=Lax leaves open to sibling subdomains.
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.
Why
/api/trpcshipped the starter-kit CORS block (Access-Control-Allow-Origin: *,Allow-Headers: *, anOPTIONShandler). The app is same-origin only, so this only widened the attack surface.CSRF protection relied solely on iron-session's default
SameSite=Lax. Lax treats every*.a5x.aisibling as same-site, so XSS on another subdomain, or a subdomain takeover via a dangling CNAME, could send cookie-authenticated tRPC mutations.multipart/form-datais accepted by tRPC v11 and needs no preflight.What
setCorsHeadersand theOPTIONSexport from the tRPC route.isCrossSiteRequest()toserver/utils/request.ts: non-GET/HEAD requests whoseSec-Fetch-Siteis anything other thansame-origin/noneget a 403.Other
/api/*routes are unchanged; they use their own token/bearer auth and some have external callers.Tests
server/utils/__tests__/request.spec.ts: allowed vs. flaggedSec-Fetch-Sitevalues, missing header, safe methods.app/api/trpc/[trpc]/__tests__/route.spec.ts: cross-site POST → 403, same-origin passes through, no CORS headers orOPTIONSexport.Same patch applied across dev-kit, etp-compass, athena, etp-purser, etp-herald.