Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/webapp/app/services/sessionStorage.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const DEFAULT_SESSION_DURATION_SECONDS = 31_556_952;
export const sessionStorage = createCookieSessionStorage({
cookie: {
name: "__session",
sameSite: "lax",
sameSite: env.NODE_ENV === "production" ? "none" : "lax",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Changing sameSite to "none" in production removes CSRF protection from the session cookie

Setting sameSite: "none" means the __session cookie will be sent on all cross-site requests in production. The application has no alternative CSRF protection mechanism — no CSRF tokens, no double-submit cookies — as confirmed by searching the codebase for "csrf"/"CSRF". The only references to CSRF in the entire webapp are comments noting that sameSite: "lax" itself is the CSRF defense (e.g. apps/webapp/app/services/impersonation.server.ts:12). Every other cookie in the app (impersonation, onboardingSession, referralSource, redirectTo, gitHubSession, lastAuthMethod, uiPreferences, OAuth state cookies) all remain sameSite: "lax". An attacker could host a page that issues POST requests (or other state-changing methods) to the Trigger.dev webapp, and the victim's session cookie would be included automatically — allowing task triggers, settings changes, or other authenticated actions without consent.

Prompt for agents
The change from sameSite: 'lax' to sameSite: 'none' removes the application's only CSRF protection for the session cookie. The app has no CSRF token mechanism to compensate.

If cross-site cookie sending is genuinely needed (e.g. for an iframe embed scenario), you must add an alternative CSRF protection layer — such as per-request CSRF tokens verified on state-changing endpoints, or Origin/Referer header validation. Without such a mechanism, any authenticated POST/PUT/DELETE endpoint is vulnerable to cross-site request forgery.

If the cross-site requirement is narrow (e.g. only needed for specific API endpoints), consider keeping sameSite: 'lax' on the session cookie and using a separate authentication mechanism (like Bearer tokens) for the cross-site use case.

Relevant files: apps/webapp/app/services/sessionStorage.server.ts (the changed file), apps/webapp/app/services/impersonation.server.ts:12 (comment confirming lax = CSRF defense).
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 All other cookies in the webapp remain sameSite: "lax" — inconsistent security posture

Every other cookie-based session storage in the webapp hardcodes sameSite: "lax": OAuth state cookies (auth.google.ts:35, auth.github.ts:35), impersonation (impersonation.server.ts:12), onboarding (onboardingSession.server.ts:7), redirect (redirectTo.server.ts:12), referral (referralSource.server.ts:15), GitHub session (gitHubSession.server.ts:12), UI preferences (uiPreferences.server.ts:7), last auth method (lastAuthMethod.server.ts:10), and messages (message.server.ts:42). The main session cookie is the only one being changed to "none". If the intent is to support cross-origin embedding, the other cookies (especially OAuth state cookies) would also need updating, otherwise cross-origin login flows would still fail since the OAuth cookies wouldn't be sent.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

path: "/",
httpOnly: true,
secrets: [env.SESSION_SECRET],
Expand Down