From acc
Analyzes PHP code for CSRF vulnerabilities like missing tokens, state-changing GET requests, and token validation gaps. Use when auditing web app forms and APIs.
How this skill is triggered — by the user, by Claude, or both
Slash command
/acc:check-csrf-protectionThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Analyze PHP code for Cross-Site Request Forgery vulnerabilities.
Analyze PHP code for Cross-Site Request Forgery vulnerabilities.
// CRITICAL: Form without CSRF token
<form method="POST" action="/transfer">
<input name="amount" value="1000">
<input name="to" value="attacker">
<button>Transfer</button>
</form>
// CRITICAL: No token validation
public function transfer(Request $request): Response
{
$amount = $request->get('amount');
$to = $request->get('to');
$this->bankService->transfer($amount, $to);
// No CSRF check!
}
// CRITICAL: Modification via GET
#[Route('/user/delete/{id}', methods: ['GET'])]
public function deleteUser(int $id): Response
{
$this->userService->delete($id);
}
// CRITICAL: Toggle via GET
#[Route('/user/activate/{id}')]
public function activateUser(int $id): Response
{
$user = $this->userRepository->find($id);
$user->setActive(true);
}
// VULNERABLE: Logout via GET (session hijacking)
<a href="/logout">Logout</a>
// VULNERABLE: Token not validated server-side
public function handle(Request $request): Response
{
// Frontend sends token but backend doesn't check
$this->processPayment($request);
}
// VULNERABLE: Weak token validation
if ($request->get('_token')) { // Just checks existence
$this->process();
}
// VULNERABLE: Token not regenerated after login
session_start();
$_SESSION['user'] = $user;
// CSRF token remains same from anonymous session
// VULNERABLE: No CSRF for AJAX
fetch('/api/update', {
method: 'POST',
body: JSON.stringify(data)
});
// VULNERABLE: Only Origin check, no token
if ($_SERVER['HTTP_ORIGIN'] === 'https://example.com') {
$this->process(); // Origin can be spoofed in some scenarios
}
// VULNERABLE: CORS misconfiguration
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials: true');
// VULNERABLE: Token in cookie only
setcookie('csrf_token', $token);
// Attacker can't read but browser sends automatically
// CORRECT: Double Submit Cookie pattern
// Token in cookie AND in request header/body
// Server compares both values
// LESS SECURE: Same token for entire session
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
// MORE SECURE: New token per form
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_tokens'][] = $token; // Store multiple
// VULNERABLE: Third-party script without SRI
<script src="https://cdn.example.com/lib.js"></script>
// CORRECT: With subresource integrity
<script src="https://cdn.example.com/lib.js"
integrity="sha384-abc123..."
crossorigin="anonymous"></script>
// VULNERABLE: No SameSite attribute
setcookie('session_id', $sessionId);
// CORRECT: SameSite=Strict
setcookie('session_id', $sessionId, [
'samesite' => 'Strict', // or 'Lax'
'secure' => true,
'httponly' => true
]);
# Forms without csrf token
Grep: '<form[^>]*method=["\']post["\'][^>]*>' -i --glob "**/*.php"
Grep: 'csrf|_token|token' --glob "**/*.php"
# GET routes that modify state
Grep: '#\[Route.*methods:.*GET.*\]' --glob "**/*.php"
Grep: 'public function delete|update|create' --glob "**/*.php"
# Cookie without samesite
Grep: "setcookie\([^)]+\)\s*;" --glob "**/*.php"
# CORS allow all
Grep: "Access-Control-Allow-Origin.*\*" --glob "**/*.php"
| Pattern | Severity |
|---|---|
| State change via GET | 🔴 Critical |
| No CSRF token on forms | 🔴 Critical |
| Token not validated | 🔴 Critical |
| Missing SameSite cookie | 🟠 Major |
| Token per session only | 🟡 Minor |
// Symfony
{{ csrf_token('authenticate') }}
// Laravel Blade
@csrf
// Validation
$request->validate([
'_token' => 'required|string'
]);
// Generate
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;
// Include in form
<input type="hidden" name="_token" value="<?= $token ?>">
// Validate
if (!hash_equals($_SESSION['csrf_token'], $_POST['_token'])) {
throw new CsrfException();
}
// Use custom header (can't be set cross-origin)
fetch('/api/update', {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify(data)
});
// Server validates header
$token = $request->headers->get('X-CSRF-Token');
if (!$this->csrfManager->isValid($token)) {
throw new CsrfException();
}
session_start([
'cookie_samesite' => 'Strict', // Prevents cross-site sending
'cookie_secure' => true,
'cookie_httponly' => true,
]);
### CSRF Vulnerability: [Description]
**Severity:** 🔴/🟠/🟡
**Location:** `file.php:line`
**CWE:** CWE-352 (Cross-Site Request Forgery)
**Issue:**
[Description of the CSRF weakness]
**Attack Vector:**
Attacker creates malicious page that submits form to victim's browser.
**Code:**
```php
// Vulnerable code
Fix:
// With CSRF protection
npx claudepluginhub dykyi-roman/awesome-claude-code --plugin accValidates CSRF protections in web apps: inventories state-changing endpoints, audits synchronizer tokens, double-submit cookies, SameSite, Origin/Referer headers for gaps.
Detects missing CSRF protection in forms, state-changing endpoints, and session cookie config. Use when writing HTML forms, setting CSRF middleware, or disabling framework protections.
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.