Tested fixes for CWE-352 in Express, Flask, Spring Boot, ASP.NET Core, Django, Rails and Laravel: the vulnerable code, the fix, a plausible fix that still fails, and the regression tests.
MITRE’s description of CWE-352: The web application does not, or cannot, sufficiently verify whether a request was intentionally provided by the user who sent the request, which could have originated from an unauthorized actor.
Common consequences MITRE lists
- Confidentiality, Integrity, Availability, Non-Repudiation, Access Control: Gain Privileges or Assume Identity; Bypass Protection Mechanism; Read Application Data; Modify Application Data; DoS: Crash, Exit, or Restart
Any site the user visits can trigger state-changing requests that carry their cookies, so settings, payments or account details change without the user meaning it.
- Reject cross-site state-changing requests by checking
Sec-Fetch-SiteorOrigin, and use a synchronizer or double-submit token where those signals are unavailable. - Set session cookies with
SameSite=LaxorStrictas defense in depth; it does not stop requests from sibling subdomains, which count as same-site. - Never change state on
GET,HEADor other safe methods. - Ask the user to re-authenticate or confirm before high-impact changes such as email, password or payout details.
Guides on this site
Protect cookie-authenticated actions against CSRF
Make the server distinguish an intended action from a request another site caused the browser to send.
Configure CORS and CSP around the browser capabilities you need
Control who can read API responses and which resources a page may execute without confusing either control with authorization.
Preserve framework security controls across the request lifecycle
Trace middleware, persistence and rendering so custom code does not bypass the protections supplied by the framework.
Defend OAuth and OIDC against redirect and token attacks
Apply RFC 9700 and RFC 10017: exact redirect matching, PKCE with downgrade protection, state and iss binding, refresh-token rotation, sender-constrained tokens, and a backend-for-frontend so browser tokens cannot be stolen.
OAuth 2.0 and OpenID Connect login: authorization code with PKCE
Implement OAuth 2.0 and OpenID Connect login with the authorization code flow and PKCE, keep each transaction bound to its browser, and block redirect, mix-up, code-injection and token-theft attacks.
Practice
- CSRF lab: Protect an account change from a forged request · Browser lab
- CORS policy lab: Grant CORS to the right origins only · Browser lab
- CSP builder lab: Build a strict Content-Security-Policy · Browser lab
- OAuth redirect and PKCE lab: Match redirect URIs and verify PKCE · Browser lab
- Secure a real HTTP API · Local project
References
- CWE-352 in the MITRE CWE list (version 4.20)
- 2025 CWE Top 25 Most Dangerous Software Weaknesses (MITRE CWE Program)
- OWASP Cross-Site Request Forgery Prevention Cheat Sheet
List data from MITRE; the name, definition and consequences are from MITRE’s CWE 4.20 catalogue. A guide is listed as the main subject when the weakness is what the guide is about, and as covering it when a dedicated section or worked example addresses it.
CWE content: Copyright © 2006–2026, The MITRE Corporation. CWE, CWSS, CWRAF, and the CWE logo are trademarks of The MITRE Corporation. CWE™ is free to use by any organization or individual for any research, development, and/or commercial purposes, per these CWE Terms of Use. Accordingly, The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE is a trademark of The MITRE Corporation. CWE Terms of Use.