T09 · Insecure Skill Coding Practices
Warning
- Location
references/actions.md:154- Finding
Misleading Claim of Built-In CSRF Protection
- Content
View full analysis
` and `useFetcher`. Use `useFetcher().submit()` or `useFetcher().load()` instead — same UX without a URL change, and Remix wires up the lifecycle for you. ``` ### Technical Analysis The guidance incorrectly implies that Remix `` and `useFetcher` provide built-in CSRF protection. These APIs integrate submissions with Remix navigation, pending-state handling, progressive enhancement, and loader revalidation, but they do not inherently generate or validate anti-CSRF tokens. Applications that rely on this statement may implement cookie-authenticated mutation actions without an explicit CSRF defense. A cross-origin HTML form can submit a simple POST request to such an action. If the browser attaches an eligible session cookie—for example, because of the application's cookie configuration—the server may treat the forged request as authenticated. Using `` or `useFetcher` on the legitimate page does not prevent an attacker from constructing an independent request. CSRF protection must therefore be enforced by the server and must not be treated as an automatic property of these Remix APIs. ### Attack Path 1. An application implements a state-changing Remix action protected only by a session cookie. 2. Based on the audited guidance, the developer assumes that using `` or `useFetcher` supplies sufficient CSRF protection and adds no server-side token or origin validation. 3. A victim signs in to the application. 4. An attacker hosts a page containing a cross-origin form targeting the vulnerable action. 5. The victim visits the attacker-controlled page, which submits the forged reque ...[truncated 877 chars]- Remediation
View remediation
` and `useFetcher` provide built-in CSRF protection. 2. Clarify that these APIs provide Remix lifecycle integration, not request-authenticity validation. 3. Require an explicit server-side CSRF defense for cookie-authenticated mutations: - Generate a cryptographically random CSRF token associated with the user's session. - Include the token in each state-changing form submission. - Validate it using a timing-safe comparison before performing the mutation. - Alternatively, use a correctly implemented signed double-submit-cookie pattern. 4. Validate the `Origin` header for state-changing requests and reject origins outside an explicit allowlist. Where appropriate, also evaluate `Sec-Fetch-Site` as a defense-in-depth signal. 5. Configure session cookies with `Secure`, `HttpOnly`, and the most restrictive practical `SameSite` policy. Do not rely on `SameSite` as the sole CSRF defense. 6. Enforce authorization independently for every action, even after CSRF validation. 7. Restrict accepted methods and content types where practical, and reject unexpected request formats. 8. Replace the affected sentence with guidance such as: ```md Calling `fetch()` directly bypasses Remix revalidation, pending-state handling, and progressive enhancement. Prefer `` or `useFetcher` for Remix lifecycle integration. These APIs do not automatically provide CSRF protection; cookie-authenticated mutation actions still require explicit server-side CSRF defenses. ``` ]]>
