csrf-protection
Cross-Site Request Forgery prevention techniques. Use this skill when implementing forms, state-changing operations, or reviewing CSRF protections. Activate when: CSRF, cross-site request forgery, form security, token validation, same-site cookie, state changing request, POST request security.
What this skill does
# CSRF Protection
**Prevent Cross-Site Request Forgery attacks on your web application.**
## When to Use
- Implementing forms that change state
- Building APIs consumed by browsers
- Setting up session cookies
- Reviewing authentication flows
- Any state-changing POST/PUT/DELETE requests
## How CSRF Works
```html
<!-- Attacker's malicious page -->
<html>
<body onload="document.forms[0].submit()">
<form action="https://bank.com/transfer" method="POST">
<input name="to" value="attacker" />
<input name="amount" value="10000" />
</form>
</body>
</html>
<!-- Victim visits this page while logged into bank.com -->
<!-- Their session cookie is sent automatically! -->
```
## Protection Methods
### 1. SameSite Cookies (Primary Defense)
```javascript
// Express session with SameSite
app.use(session({
secret: process.env.SESSION_SECRET,
cookie: {
httpOnly: true,
secure: true, // HTTPS only
sameSite: 'strict', // Or 'lax' for better UX
maxAge: 3600000
}
}));
// Set-Cookie header result:
// Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict
```
**SameSite Options:**
| Value | Behavior |
|-------|----------|
| `Strict` | Cookie never sent cross-site |
| `Lax` | Sent on top-level navigation (default) |
| `None` | Always sent (requires Secure) |
### 2. CSRF Tokens (Defense in Depth)
```javascript
const csrf = require('csurf');
// Setup CSRF middleware
const csrfProtection = csrf({
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict'
}
});
// Apply to routes
app.get('/form', csrfProtection, (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
app.post('/submit', csrfProtection, (req, res) => {
// Token automatically validated by middleware
// Process form...
});
```
```html
<!-- In your form template -->
<form method="POST" action="/submit">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<!-- Other form fields -->
<button type="submit">Submit</button>
</form>
```
### 3. Double Submit Cookie Pattern
```javascript
// Generate CSRF token
function generateCsrfToken() {
return crypto.randomBytes(32).toString('hex');
}
// Set token in cookie and return for form
app.get('/form', (req, res) => {
const token = generateCsrfToken();
res.cookie('csrf-token', token, {
httpOnly: false, // JS needs to read this
secure: true,
sameSite: 'strict'
});
res.render('form', { csrfToken: token });
});
// Validate both match
app.post('/submit', (req, res) => {
const cookieToken = req.cookies['csrf-token'];
const bodyToken = req.body._csrf || req.headers['x-csrf-token'];
if (!cookieToken || !bodyToken ||
!crypto.timingSafeEqual(Buffer.from(cookieToken), Buffer.from(bodyToken))) {
return res.status(403).json({ error: 'Invalid CSRF token' });
}
// Process request...
});
```
### 4. Custom Header Verification (for APIs)
```javascript
// Require custom header that can't be set cross-origin
function csrfHeaderCheck(req, res, next) {
// Browsers block cross-origin custom headers
const csrfHeader = req.headers['x-requested-with'];
if (csrfHeader !== 'XMLHttpRequest') {
return res.status(403).json({ error: 'CSRF validation failed' });
}
next();
}
// Apply to API routes
app.use('/api', csrfHeaderCheck);
```
```javascript
// Client-side
fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest' // Custom header
},
body: JSON.stringify(data),
credentials: 'include'
});
```
### 5. Origin/Referer Validation
```javascript
function validateOrigin(req, res, next) {
const origin = req.headers.origin || req.headers.referer;
if (!origin) {
// Might be same-origin request - additional checks needed
return next();
}
try {
const url = new URL(origin);
const allowedOrigins = [
'https://example.com',
'https://www.example.com'
];
if (!allowedOrigins.includes(url.origin)) {
return res.status(403).json({ error: 'Invalid origin' });
}
} catch {
return res.status(403).json({ error: 'Invalid origin header' });
}
next();
}
```
## Framework-Specific Implementation
### React (with fetch)
```jsx
// Get CSRF token from meta tag or cookie
function getCsrfToken() {
return document.querySelector('meta[name="csrf-token"]')?.content
|| document.cookie.match(/csrf-token=([^;]+)/)?.[1];
}
// Custom fetch wrapper
async function secureFetch(url, options = {}) {
const csrfToken = getCsrfToken();
return fetch(url, {
...options,
credentials: 'include',
headers: {
...options.headers,
'X-CSRF-Token': csrfToken
}
});
}
// Usage
await secureFetch('/api/update', {
method: 'POST',
body: JSON.stringify(data)
});
```
### Django
```python
# settings.py - CSRF is enabled by default
MIDDLEWARE = [
'django.middleware.csrf.CsrfViewMiddleware',
# ...
]
# In templates
<form method="post">
{% csrf_token %}
<!-- form fields -->
</form>
# For AJAX
<script>
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
fetch('/api/endpoint', {
method: 'POST',
headers: {
'X-CSRFToken': csrftoken
},
body: JSON.stringify(data)
});
</script>
```
### Rails
```ruby
# ApplicationController
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
end
# In views
<%= form_with url: '/submit' do |f| %>
<!-- CSRF token automatically included -->
<% end %>
# For AJAX (Rails UJS handles this automatically)
# Or manually:
headers: {
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
}
```
### Laravel
```php
// In Blade templates
<form method="POST" action="/submit">
@csrf
<!-- form fields -->
</form>
// For AJAX - token in meta tag
<meta name="csrf-token" content="{{ csrf_token() }}">
// JavaScript
fetch('/api/endpoint', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
}
});
```
## Common Mistakes
```javascript
// MISTAKE 1: CSRF token in URL (visible in logs/history)
<a href="/delete?csrf=abc123">Delete</a> // BAD
// MISTAKE 2: Not validating on state-changing requests
app.get('/delete/:id', deleteHandler); // GET shouldn't change state
// MISTAKE 3: Accepting token from any location
const token = req.query.csrf || req.body.csrf; // Don't check query!
// MISTAKE 4: SameSite=None without understanding
cookie: { sameSite: 'none', secure: true } // Opens CSRF risk
// MISTAKE 5: Not regenerating token after login
// Token should change when auth state changes
```
## Testing CSRF Protection
```html
<!-- Test page (host on different domain) -->
<!DOCTYPE html>
<html>
<body>
<h1>CSRF Test</h1>
<!-- Test 1: Form submission -->
<form id="test1" action="http://target.com/api/update" method="POST">
<input name="data" value="malicious">
</form>
<!-- Test 2: Fetch request -->
<script>
fetch('http://target.com/api/update', {
method: 'POST',
credentials: 'include',
body: JSON.stringify({ data: 'malicious' })
}).then(r => console.log('Fetch result:', r.status));
</script>
<!-- Test 3: Image tag (for GET requests) -->
<img src="http://target.com/api/delete?id=1" />
</body>
</html>
```
## Code Review Checklist
- [ ] SameSite cookie attribute set (Strict or Lax)
- [ ] CSRF tokens on all state-changing forms
- [ ] Tokens validated server-side
- [ ] Tokens regenerated on authentication changes
- [ ] No state changes on GET requests
- [ ] Origin/Referer validated for sensitive operations
- [ ] CORS properly configured
- [ ] Custom headers required for API calls
## Best Practices
1. **Use SameSite Cookies**: First line of defense
2. **Add CSRF Tokens**: Defense in depth
3. **Validate Origin**: Extra layer for sensitive ops
4. **No State Changes on GET**: REST properly
5. **RegeRelated in Security
mac-ops
IncludedComprehensive macOS workstation operations — diagnose kernel panics, identify failing drives, audit launchd startup items, decode wake reasons, triage TCC permission denials, manage APFS snapshots, recover from no-boot. Use for: Mac is slow, slow bootup, won't boot, kernel panic, kernel_task hot, mds_stores CPU, photoanalysisd, cloudd, login loop, gray screen, sleep wake failure, drive failing, IO errors, APFS snapshots eating space, Time Machine local snapshots, Spotlight indexing, launchd, LaunchAgent, LaunchDaemon, login items, TCC permissions, Full Disk Access, Screen Recording denied, Gatekeeper, quarantine, com.apple.quarantine, app is damaged, helper tool, /Library/PrivilegedHelperTools, pmset, wake reasons, dark wake, sysdiagnose, panic.ips, DiagnosticReports, configuration profile, MDM profile, remote diagnostics over SSH.
a11y-audit
IncludedRun accessibility audits on web projects combining automated scanning (axe-core, Lighthouse) with WCAG 2.1 AA compliance mapping, manual check guidance, and structured reporting. Output is configurable: markdown report only, markdown plus machine-readable JSON, or markdown plus issue tracker integration. Use this skill whenever the user mentions "accessibility audit", "a11y audit", "WCAG audit", "accessibility check", "compliance scan", or asks to check a web project for accessibility issues. Also trigger when the user wants to verify WCAG conformance or map findings to a specific standard (CAN-ASC-6.2, EN 301 549, ADA/AODA).
erpclaw
IncludedAI-native ERP system with self-extending OS. Full accounting, invoicing, inventory, purchasing, tax, billing, HR, payroll, advanced accounting (ASC 606/842, intercompany, consolidation), and financial reporting. 413 actions across 14 domains, 43 expansion modules. Constitutional guardrails, adversarial audit, schema migration. Double-entry GL, immutable audit trail, US GAAP.
assess
IncludedAssesses and rates quality 0-10 across multiple dimensions (correctness, maintainability, security, performance, testability, simplicity) with pros/cons analysis. Compares against project conventions and prior decisions from memory. Produces structured evaluation reports with actionable improvement suggestions. Use when evaluating code, designs, architectures, or comparing alternative approaches.
spring-boot-security-jwt
IncludedProvides JWT authentication and authorization patterns for Spring Boot 3.5.x covering token generation with JJWT, Bearer/cookie authentication, database/OAuth2 integration, and RBAC/permission-based access control using Spring Security 6.x. Use when implementing authentication or authorization in Spring Boot applications.
code-hardcode-audit
IncludedDetect hardcoded values, magic numbers, and leaked secrets. TRIGGERS - hardcode audit, magic numbers, PLR2004, secret scanning.