Help us improve
Share bugs, ideas, or general feedback.
From grimoire
Protects state-changing endpoints (POST, PUT, PATCH, DELETE) from cross-site request forgery using synchronizer tokens, SameSite cookies, or origin verification.
npx claudepluginhub jeffreytse/grimoire --plugin grimoireHow this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:prevent-csrfThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Protect state-changing endpoints from cross-site request forgery using synchronizer tokens, SameSite cookies, or origin verification — ensuring requests originate from your own application.
Prevents CSRF attacks by validating request origin and using unpredictable tokens for state-changing operations. Covers SameSite cookies, sync token pattern, double-submit cookie pattern, and origin header validation.
Validates CSRF protections in web apps: inventories state-changing endpoints, audits synchronizer tokens, double-submit cookies, SameSite, Origin/Referer headers for gaps.
Implements CSRF protection using synchronizer tokens, double-submit cookies, and SameSite attributes. Secures web forms, state-changing endpoints, and authentication layers.
Share bugs, ideas, or general feedback.
Protect state-changing endpoints from cross-site request forgery using synchronizer tokens, SameSite cookies, or origin verification — ensuring requests originate from your own application.
Adopted by: Django, Rails, Laravel, Spring Security, and ASP.NET all include CSRF protection by default. OWASP Top 10 2021 (A01:Broken Access Control) covers CSRF. PCI DSS v4.0 Requirement 6.2.4 requires protection against CSRF. GitHub, Google, and Stripe use SameSite cookies as the primary defense.
Impact: CSRF allows attackers to perform unauthorized actions on behalf of authenticated users — fund transfers, email changes, password resets — by tricking them into visiting a malicious page. Twitter, Netflix, and YouTube have all had critical CSRF vulnerabilities. Proper implementation eliminates the entire attack class.
Why best: The Synchronizer Token Pattern and SameSite cookies are complementary defenses that cover different attack vectors. Relying on Referer header alone fails because it can be stripped by browsers or proxies.
Sources: OWASP CSRF Prevention Cheat Sheet; CWE-352; OWASP Top 10 2021
Set SameSite=Lax (or Strict) on all session cookies — this is the primary defense for modern browsers. Lax blocks CSRF for POST/PUT/DELETE while allowing cross-site GET navigation (e.g., following links). Strict blocks all cross-site requests including GET.
Set-Cookie: session=abc123; SameSite=Lax; Secure; HttpOnly; Path=/
Use Strict when your app is not embedded in other sites. Use Lax for general-purpose apps.
Add a Synchronizer CSRF Token for defense-in-depth — generate a random, unpredictable token per session (or per request for high-security actions), store server-side, validate on every state-changing request.
<!-- Include in every HTML form -->
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
# On submit: verify token matches session
if request.form['csrf_token'] != session['csrf_token']:
abort(403)
For SPAs using JSON APIs — use the Double Submit Cookie pattern or a custom request header:
HttpOnly cookie with a random value.X-CSRF-Token).fetch('/api/transfer', {
method: 'POST',
headers: { 'X-CSRF-Token': getCookie('csrf') },
body: JSON.stringify(data)
});
Verify Origin or Referer header as a secondary check — reject requests where Origin doesn't match your site's origin. Do not use this as the sole defense (it can be absent).
allowed_origins = {'https://app.example.com'}
if request.headers.get('Origin') not in allowed_origins:
abort(403)
Apply CSRF protection to all state-changing endpoints — POST, PUT, PATCH, DELETE, and any GET endpoint that performs side effects. Explicitly exempt read-only GET/HEAD/OPTIONS.
Use framework-provided CSRF middleware — don't implement from scratch. Django: CsrfViewMiddleware (enabled by default). Rails: protect_from_forgery. Spring: CsrfFilter. Laravel: VerifyCsrfToken.
SameSite=None without understanding the implications — required for embedded iframes or cross-site widgets, but eliminates SameSite CSRF protection.localStorage — fine, but XSS can steal it; HttpOnly cookies protect session tokens but not CSRF tokens (by design).