Interlace ESLint
ESLint Interlace
ExpressRules

require-csrf-protection

**Severity:** � High

Require CSRF protection middleware for state-changing HTTP methods

Severity: 🔴 High
CWE: CWE-352

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

🔒 CWE-352 OWASP:A01 CVSS:8.8 | Cross-Site Request Forgery (CSRF) detected | HIGH
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A01_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-352 OWASP:A01 CVSS:8.8
Issue DescriptionSpecific vulnerabilityCross-Site Request Forgery (CSRF) detected
Severity & ComplianceImpact assessmentHIGH
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Rule Details

This rule detects Express.js routes handling state-changing requests (POST, PUT, PATCH, DELETE) without CSRF protection. CSRF attacks trick authenticated users into performing unwanted actions.

Examples

❌ Incorrect

import express from 'express';
const app = express();

// POST without CSRF protection - VULNERABLE
app.post('/transfer', (req, res) => {
  transferFunds(req.body);
});

✅ Correct

import express from 'express';
import csrf from 'csurf';

const app = express();
const csrfProtection = csrf({ cookie: true });

// Global CSRF protection
app.use(csrfProtection);

app.post('/transfer', (req, res) => {
  transferFunds(req.body);
});

// Or per-route protection
app.post('/transfer', csrfProtection, (req, res) => {
  transferFunds(req.body);
});

Options

OptionTypeDefaultDescription
allowInTestsbooleanfalseAllow missing CSRF in test files
protectedMethodsstring[]['post', 'put', 'patch', 'delete']HTTP methods that require CSRF protection
ignorePatternsstring[][]Route patterns to ignore (e.g., /api/webhook)
{
  "rules": {
    "express-security/require-csrf-protection": [
      "error",
      {
        "ignorePatterns": ["/api/webhook", "/api/public/.*"]
      }
    ]
  }
}

When Not To Use It

Disable for:

  • Stateless API-only backends using token-based auth (JWT)
  • Webhook endpoints that use signature verification
  • Public APIs without session-based authentication

Known False Negatives

The following patterns are not detected due to static analysis limitations:

CSRF Middleware in External Router

Why: Middleware applied in other modules is not tracked.

// ❌ NOT DETECTED - CSRF in external router file
// routes.ts applies csrf, but main.ts doesn't see it
import { router } from './routes';
app.use(router);

Mitigation: Apply CSRF globally in main file. Document middleware location.

Custom CSRF Implementation

Why: Custom CSRF token validation is not recognized.

// ❌ NOT DETECTED - Custom CSRF check
app.post('/transfer', (req, res) => {
  if (req.headers['x-csrf-token'] !== req.session.csrf) {
    return res.status(403).send('Invalid CSRF');
  }
  // ... handle request
});

Mitigation: Configure rule to recognize custom middleware names.

Framework CSRF Abstraction

Why: Framework-specific CSRF is not detected.

// ❌ NOT DETECTED - Next.js API routes
export async function POST(req) {
  // Next.js has different CSRF handling
}

Mitigation: Use framework-specific linting. Configure ignorePatterns.

Token-Based API with Session Fallback

Why: Rule can't determine if endpoint uses session or JWT.

// ❌ FALSE POSITIVE RISK - JWT API doesn't need CSRF
app.post('/api/data', jwtAuth, (req, res) => {
  // Safe: JWT auth, not session-based
});

Mitigation: Use ignorePatterns for API routes. Document auth strategy.

Further Reading

On this page