# State-changing endpoint without CSRF token

GET or POST routes that mutate state but never verify a CSRF token, especially email-link and JSON flows

_Area: Web business logic and race conditions. Seen in 3 disclosed reports; latest 2020-03-30. Updated 2026-10-24._

## How it works
A state-changing route trusts that the request came from the app's own UI, but never proves it. The browser attaches the victim's session cookie to any cross-site request, so an attacker page can trigger the action in the victim's authenticated context. The broken assumption: "only our frontend calls this endpoint." Email-link flows and JSON-only endpoints often skip tokens because their authors assumed the link or content-type was protection enough [E1](https://bugbountylibrary.com/r/h1%3A416978.md)[E2](https://bugbountylibrary.com/r/h1%3A251918.md).

## Where it shows up
- Admin or account actions reachable as a bare GET, especially ones behind a login-redirect URL from an email [E1](https://bugbountylibrary.com/r/h1%3A416978.md)
- Endpoints that require `application/json` and therefore skip tokens, assuming form CSRF is impossible [E2](https://bugbountylibrary.com/r/h1%3A251918.md)
- Hidden storefront routes (gift-cert, cart, transfer) with no token on the mutating POST [E3](https://bugbountylibrary.com/r/h1%3A206319.md)
- Legacy Flash `crossdomain.xml` permitting cross-origin requests plus 307 redirects that preserve method and body [E2](https://bugbountylibrary.com/r/h1%3A251918.md)
- Actions with persistent server-side side effects that the victim cannot undo [E3](https://bugbountylibrary.com/r/h1%3A206319.md)

## How to review
For every route that changes state, confirm a per-session, unpredictable token is required and validated server-side, and that GET requests never mutate. Check that the token check happens before the action, not after. For JSON endpoints, verify the token is still enforced rather than relying on content-type. The invariant: no state change occurs unless the request carries a valid CSRF token bound to the victim's session, regardless of HTTP method, content-type, or how the request was initiated.

## Variants seen
- State-changing GET on an inter-shop domain transfer, triggered by a cross-site image load [E1](https://bugbountylibrary.com/r/h1%3A416978.md)
- JSON POST with no token, reached cross-origin via Flash and a 307 redirect [E2](https://bugbountylibrary.com/r/h1%3A251918.md)
- Unauthenticated CSRF on a gift-cert add-to-basket that persists and blocks checkout [E3](https://bugbountylibrary.com/r/h1%3A206319.md)

## Impact and severity
Led to attacker-controlled domain/DNS injection into a victim store [E1](https://bugbountylibrary.com/r/h1%3A416978.md), unauthorized setting changes [E2](https://bugbountylibrary.com/r/h1%3A251918.md), and a persistent denial of checkout and payment [E3](https://bugbountylibrary.com/r/h1%3A206319.md). Severity rises when the action is irreversible or persists across sessions, and when it touches payments or account ownership.

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A416978.md
- E2: https://bugbountylibrary.com/r/h1%3A251918.md
- E3: https://bugbountylibrary.com/r/h1%3A206319.md
