# CSRF protection imported is actually applied

- **Pattern:** `ab-000280` (`ai-slop-security-theater.unapplied-middleware.csrf-imported-and-applied`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000280
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000280)

## Why it matters

Installing `csurf` or `csrf-csrf` and never calling `app.use(csrfProtection)` or the library's equivalent wrapper leaves every state-mutating route open to cross-site request forgery. OWASP A01 (Broken Access Control) and CWE-352 describe the attack: a malicious third-party page can POST to your `/api/transfer` endpoint using a victim's session cookie, and your server will accept it as a legitimate request. The library is evidence that the developer knew CSRF was a risk — the installation without application is the exact theater pattern.

## Severity rationale

High because every state-mutating endpoint is CSRF-vulnerable, enabling unauthorized actions on behalf of authenticated users from attacker-controlled pages.

## Remediation

Apply the CSRF middleware to all state-mutating routes. For Express with `csurf`:

```ts
import csurf from 'csurf'
const csrfProtection = csurf({ cookie: true })

// Apply to individual routes
app.post('/api/transfer', csrfProtection, handler)

// Or globally, then exclude safe methods
app.use(csrfProtection)
```

For Next.js App Router, use `csrf-csrf` or `@edge-csrf/nextjs` and wrap your API handlers. Verify the token is read from a header or double-submit cookie, not just from `req.body`. The CSRF token must be included in every form or mutation client request.

## Detection

- **ID:** `csrf-imported-and-applied`
- **Severity:** `high`
- **What to look for:** When any of these CSRF libraries is in `package.json` dependencies — `csurf`, `csrf`, `next-csrf`, `@edge-csrf/nextjs`, `@edge-csrf/core`, `csrf-csrf`, `tiny-csrf` — walk source files and count all imports (at least 1 required) and all calls that apply it as middleware: `app.use(csurf(`, `app.use(csrf(`, `csrfProtection(`, an Express middleware setup, OR (for Next.js libraries) the wrapper pattern documented for that library.
- **Pass criteria:** A CSRF library from the allowlist is imported in at least 1 source file AND a corresponding `app.use(csurf(` or wrapper application call exists somewhere in the application chain.
- **Report even on pass:** "CSRF library: [name] imported in [file] AND applied in [file]."
- **Fail criteria:** A CSRF library is imported but no application call exists anywhere in source.
- **Skip (N/A) when:** No CSRF library in dependencies, OR framework is Next.js App Router using only Server Actions (CSRF is built-in to Server Actions), OR auth uses JWT-in-Authorization-header only (CSRF doesn't apply to bearer tokens).
- **Cross-reference:** For broader CSRF analysis, the API Security audit (`api-security`) and SaaS Authentication audit (`saas-authentication`) cover CSRF in depth.
- **Detail on fail:** `"csurf imported in src/lib/middleware.ts but no app.use(csurf(...)) call found. CSRF library installed but not protecting any routes."`
- **Remediation:** A CSRF library is just code until you wire it into the request pipeline:

  ```ts
  // Bad: imported but unused
  import csurf from 'csurf'
  const app = express()
  app.post('/api/transfer', handler)  // unprotected

  // Good: applied as middleware
  import csurf from 'csurf'
  const csrfProtection = csurf({ cookie: true })
  app.post('/api/transfer', csrfProtection, handler)
  ```

## External references

- cwe CWE-352
- owasp A01

Taxons: placeholder-hygiene, access-control

HTML version: https://auditbuffet.com/patterns/ab-000280
