
Csrf Protection
- 328 installs
- 202 repo stars
- Updated August 4, 2026
- secondsky/claude-skills
csrf-protection is a Claude Code skill from secondsky/claude-skills that implements CSRF defenses using synchronizer tokens, double-submit cookies, and SameSite attributes for web forms and state-changing HTTP endpoints.
About
csrf-protection is a security skill in the secondsky/claude-skills security-skills suite that guides CSRF hardening for production web applications. It covers synchronizer tokens, double-submit cookies, and SameSite cookie attributes for JavaScript stacks including Express and React, plain HTML forms, and Python backends. Developers invoke it when securing login flows, payment or settings forms, and any state-changing POST, PUT, or DELETE route vulnerable to cross-site request forgery. The skill emphasizes defense-in-depth alongside authentication layers rather than replacing auth entirely. It ships beside access-control-rbac, xss-prevention, and security-headers-configuration in a six-skill security bundle installable via /plugin install security-skills@claude-skills. Reach for csrf-protection during pre-launch security passes or when audit findings flag missing anti-CSRF middleware on session-backed applications.
- csrf-protection
Csrf Protection by the numbers
- 328 all-time installs (skills.sh)
- +12 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #1,236 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/secondsky/claude-skills --skill csrf-protectionAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 328 |
|---|---|
| repo stars | ★ 202 |
| Last updated | August 4, 2026 |
| Repository | secondsky/claude-skills ↗ |
How do you add CSRF protection to web forms?
Use csrf-protection for development tasks
Who is it for?
Full-stack developers shipping session-backed web apps in Express, React, HTML, or Python who need concrete CSRF mitigation patterns before production.
Skip if: Teams building stateless JWT-only APIs with no cookie sessions where CSRF risk is negligible and other threat models take priority.
When should I use this skill?
Trigger when securing web forms, protecting state-changing endpoints, or implementing defense-in-depth authentication against CSRF attacks.
What you get
CSRF token middleware, double-submit cookie configuration, and SameSite attribute hardening on protected routes and forms.
- csrf middleware configuration
- cookie attribute policy
By the numbers
- Documents three CSRF defense patterns: synchronizer tokens, double-submit cookies, and SameSite attributes
- Bundled in the six-skill security-skills suite on secondsky/claude-skills
Files
CSRF Protection
Defend against Cross-Site Request Forgery attacks using multiple protection layers.
Protection Methods
| Method | How It Works | Browser Support |
|---|---|---|
| Synchronizer Token | Hidden form field validated server-side | All |
| Double Submit | Cookie + header must match | All |
| SameSite Cookie | Browser blocks cross-origin requests | Modern |
Token-Based Protection (Express)
const crypto = require('crypto');
function generateToken() {
return crypto.randomBytes(32).toString('hex');
}
// Middleware
app.use((req, res, next) => {
if (!req.session.csrfToken) {
req.session.csrfToken = generateToken();
}
res.locals.csrfToken = req.session.csrfToken;
next();
});
// Validation
app.post('*', (req, res, next) => {
const token = req.body._csrf || req.headers['x-csrf-token'];
if (!token || !crypto.timingSafeEqual(
Buffer.from(token),
Buffer.from(req.session.csrfToken)
)) {
return res.status(403).json({ error: 'Invalid CSRF token' });
}
next();
});SameSite Cookies
app.use(session({
cookie: {
httpOnly: true,
secure: true,
sameSite: 'strict', // or 'lax'
maxAge: 3600000
}
}));HTML Form Integration
<form method="POST" action="/transfer">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button type="submit">Submit</button>
</form>Best Practices
- Apply to all state-changing requests (POST, PUT, DELETE)
- Use SameSite=Strict for sensitive cookies
- Validate Origin/Referer headers
- Never use GET for modifications
- Implement token expiration (1 hour typical)
- Combine multiple defense layers
Additional Implementations
See references/python-react.md for:
- Flask-WTF complete CSRF setup
- React hooks for CSRF token management
- Double submit cookie pattern
Common Mistakes
- Assuming authentication prevents CSRF
- Reusing tokens across sessions
- Storing tokens in localStorage
- Missing token expiration
Python Flask and React CSRF Implementation
Flask-WTF CSRF Protection
from flask import Flask, render_template, request, jsonify
from flask_wtf.csrf import CSRFProtect, generate_csrf
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['WTF_CSRF_TIME_LIMIT'] = 3600 # 1 hour
app.config['SESSION_COOKIE_SAMESITE'] = 'Strict'
app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_HTTPONLY'] = True
csrf = CSRFProtect(app)
# Endpoint to get CSRF token for SPAs
@app.route('/api/csrf-token', methods=['GET'])
def get_csrf_token():
token = generate_csrf()
response = jsonify({'csrf_token': token})
response.set_cookie(
'XSRF-TOKEN',
token,
samesite='Strict',
secure=True
)
return response
# Exempt specific routes if needed
@app.route('/api/webhook', methods=['POST'])
@csrf.exempt
def webhook():
# Validate using signature instead
return jsonify({'status': 'ok'})
# Protected route
@app.route('/api/transfer', methods=['POST'])
def transfer():
# CSRF is automatically validated
data = request.get_json()
return jsonify({'success': True})Flask with Form Template
from flask_wtf import FlaskForm
from wtforms import StringField, DecimalField
from wtforms.validators import DataRequired
class TransferForm(FlaskForm):
recipient = StringField('Recipient', validators=[DataRequired()])
amount = DecimalField('Amount', validators=[DataRequired()])
@app.route('/transfer', methods=['GET', 'POST'])
def transfer_page():
form = TransferForm()
if form.validate_on_submit():
# Process transfer
return redirect(url_for('success'))
return render_template('transfer.html', form=form)<!-- transfer.html -->
<form method="POST">
{{ form.hidden_tag() }} <!-- Includes CSRF token -->
{{ form.recipient.label }} {{ form.recipient() }}
{{ form.amount.label }} {{ form.amount() }}
<button type="submit">Transfer</button>
</form>React Frontend Integration
// hooks/useCsrf.js
import { useState, useEffect } from 'react';
export function useCsrf() {
const [csrfToken, setCsrfToken] = useState('');
useEffect(() => {
fetch('/api/csrf-token', { credentials: 'include' })
.then(res => res.json())
.then(data => setCsrfToken(data.csrf_token));
}, []);
return csrfToken;
}
// api/client.js
export async function securePost(url, data) {
const csrfToken = document.cookie
.split('; ')
.find(row => row.startsWith('XSRF-TOKEN='))
?.split('=')[1];
return fetch(url, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken,
},
body: JSON.stringify(data),
});
}
// components/TransferForm.jsx
import { useCsrf } from '../hooks/useCsrf';
import { securePost } from '../api/client';
export function TransferForm() {
const csrfToken = useCsrf();
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const response = await securePost('/api/transfer', {
recipient: formData.get('recipient'),
amount: formData.get('amount'),
});
if (response.ok) {
// Handle success
}
};
return (
<form onSubmit={handleSubmit}>
<input type="hidden" name="_csrf" value={csrfToken} />
<input name="recipient" required />
<input name="amount" type="number" required />
<button type="submit">Transfer</button>
</form>
);
}Double Submit Cookie Pattern
import hmac
import hashlib
from functools import wraps
def validate_double_submit(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
cookie_token = request.cookies.get('XSRF-TOKEN')
header_token = request.headers.get('X-XSRF-TOKEN')
if not cookie_token or not header_token:
return jsonify({'error': 'CSRF token missing'}), 403
# Timing-safe comparison
if not hmac.compare_digest(cookie_token, header_token):
return jsonify({'error': 'CSRF token mismatch'}), 403
return fn(*args, **kwargs)
return wrapperRelated skills
How it compares
Pair csrf-protection with xss-prevention and security-headers-configuration for layered web app hardening.
FAQ
Which CSRF techniques does csrf-protection cover?
csrf-protection covers synchronizer tokens, double-submit cookies, and SameSite cookie attributes. It applies these patterns to Express and React JavaScript stacks, HTML forms, and Python backends protecting state-changing endpoints.
When should developers use csrf-protection?
csrf-protection fits when web applications use cookie-backed sessions and expose forms or state-changing routes like login, checkout, or settings updates. Stateless token APIs without cookies typically need different threat modeling.