APIs and requests
Attacks that abuse the shape of a request or the trust a browser places in your site. These are easy to miss because the normal client never sends them.
Checklist
- Protect state-changing requests from CSRF. If you authenticate with cookies, every state-changing endpoint needs a CSRF token or a strict SameSite cookie policy. If you authenticate with a bearer token in an Authorization header (not an ambient cookie), classic CSRF does not apply, which is one reason to prefer it.
- Close login-CSRF. Even the sign-in flow can be forged: bind the OAuth
stateto the browser with a cookie set at the start and checked on the callback. See authentication. - Lock down CORS. Never reflect an arbitrary
Originand never shipAccess-Control-Allow-Origin: *with credentials. Use an explicit allowlist of origins, and only the methods and headers you need. A default "allow all" is a common scaffold mistake. - Stop mass assignment. Do not spread a request body straight into a database
update. Accept an explicit allowlist of writable fields, so a user cannot send
{"role":"admin"}or{"plan":"enterprise"}and escalate. Mark read-only fields and ignore unknown ones. - Grant privileges and paid state only from a trusted event. A plan or a credit balance should change from a verified payment webhook or an admin action, never from a value in a user request.
- Verify webhooks. Check the provider's signature over the raw body, confirm the amount and currency match what you expected, and make each event idempotent so a replay cannot double-apply.
- Validate content types and sizes. Reject unexpected content types, and cap body size before you parse.
How to test
- Add
role,is_admin,plan, orcreditsto an update request and confirm the server ignores them. - Send a cross-origin request and confirm CORS does not reflect your origin.
- Replay a webhook twice and confirm it applies once.