Repository navigation
fix(web): require same-site requests for cookie-authenticated writes and set frame headers on app pages - #2997
Conversation
…and set frame headers on app pages
|
|
||
| export const isCrossSiteCookieWrite = (request: SiteCheckedRequest) => { | ||
| if (READ_ONLY_METHODS.has(request.method.toUpperCase())) return false; | ||
| if (request.headers.has("authorization")) return false; |
There was a problem hiding this comment.
Dummy headers allow cookie writes
isCrossSiteCookieWrite skips the check for any Authorization header, but callers still use the session cookie when the header is not a valid bearer token. A page served from http://localhost:3000 can pass the allowed credentialed preflight and send Authorization: Bearer other. With the user's cookie and a valid owned appId, /api/developer/credits/checkout then creates a checkout session as that user.
Apply the site check whenever authentication falls back to cookies. Only a successfully authenticated bearer should bypass it.
How this was verified: The checkout route allows the localhost origin and Authorization, the session cookie uses sameSite: "none", and getAuth reads that cookie after the header skips the site check.
Knowledge Base Used: Web API and domain services
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/database/auth/request-site.ts
Line: 39
Comment:
**Dummy headers allow cookie writes**
`isCrossSiteCookieWrite` skips the check for any `Authorization` header, but callers still use the session cookie when the header is not a valid bearer token. A page served from `http://localhost:3000` can pass the allowed credentialed preflight and send `Authorization: Bearer other`. With the user's cookie and a valid owned `appId`, `/api/developer/credits/checkout` then creates a checkout session as that user.
Apply the site check whenever authentication falls back to cookies. Only a successfully authenticated bearer should bypass it.
**How this was verified:** The checkout route allows the localhost origin and `Authorization`, the session cookie uses `sameSite: "none"`, and `getAuth` reads that cookie after the header skips the site check.
**Knowledge Base Used:** [Web API and domain services](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/web-api-and-domain-services.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.…of Authorization header
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@greptileai review |
Non-GET/HEAD/OPTIONS requests to
/apithat arrive withSec-Fetch-Site: cross-site, or with anOriginoutside the app's own host andWEB_URLwhen fetch metadata is missing, no longer pick up the session cookie in the Hono auth helpers, the EffectgetCurrentUserused by the HttpApi and RPC auth middleware, or the App Router write handlers; these requests are now treated as anonymous rather than rejected, and bearer requests are unchanged. The proxy now also sets the/loginframe headers on/dashboard,/onboarding,/invite,/cli/authorizeand/mcp/authorize.Testing
npx vitest run __tests__/unit/cookie-write-site.test.ts __tests__/unit/proxy-frame-headers.test.ts __tests__/unit/proxy-self-hosted.test.ts __tests__/unit/dev-reset-transcript.test.tsnpx vitest run __tests__/unit(all pass exceptshare-stage-identity.test.ts, which fails the same way onmain)cd apps/web && npx tsc --noEmitbun run biome check --writeon touched files

Confidence Score: 5/5
The PR appears safe to merge; the previous cookie-authentication bypass is fixed.Summary
The PR limits cookie-authenticated writes from other sites and adds frame headers to signed-in app pages.
Reviews (2) · Last reviewed commit: "fix(web): run same-site check on the coo..." · Reviewed by Greptile