# No unsafe-eval in any CSP directive

- **Pattern:** `ab-002425` (`security-headers-ii.csp-quality.no-unsafe-eval`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002425
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002425)

## Why it matters

`'unsafe-eval'` re-enables `eval()`, `Function()`, `setTimeout(string)`, and `setInterval(string)` — the four JavaScript execution surfaces that an XSS payload needs to turn a reflected string into running code. With `'unsafe-eval'` in CSP, an attacker who achieves any string injection can escalate directly to code execution, bypassing what would otherwise be a meaningful mitigation layer. CWE-79 and CWE-693 both apply. OWASP A03 (Injection) lists eval-style execution as a key XSS escalation path. The practical business impact is session hijacking, credential theft, or complete account takeover from a single injection point.

## Severity rationale

Critical because `'unsafe-eval'` turns any string injection into arbitrary code execution, nullifying CSP's primary purpose of containing XSS impact.

## Remediation

Remove `'unsafe-eval'` from every CSP directive. Most modern libraries no longer require it — verify by checking your bundler output and library changelogs.

```
# Correct: no unsafe-eval
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{perRequest}' 'strict-dynamic'
```

If a specific library requires eval (older charting libraries, some template engines), isolate it in a Web Worker with a scoped CSP rather than enabling eval globally. As a last resort, document the unavoidable dependency with an inline comment and a remediation ticket — then scope `'unsafe-eval'` to only the `script-src` directive rather than `default-src`.

## Detection

- **ID:** `no-unsafe-eval`
- **Severity:** `critical`
- **What to look for:** Parse every directive in the CSP header. For each directive, check whether it contains `'unsafe-eval'`. `unsafe-eval` enables `eval()`, `Function()`, `setTimeout(string)`, `setInterval(string)` — all XSS vectors that allow attackers to execute arbitrary code. Count all directives containing `'unsafe-eval'`.
- **Pass criteria:** 0 directives contain `'unsafe-eval'`. Count all directives and report: "X directives checked, 0 contain unsafe-eval."
- **Fail criteria:** At least 1 directive contains `'unsafe-eval'`. Count the offending directives and report: "X directives contain unsafe-eval."
- **Skip (N/A) when:** No Content-Security-Policy header configured. Run Security Headers & Basics first. Also skip if `'unsafe-eval'` is required by a documented library dependency (Angular template compiler, certain charting libraries like older Chart.js) — but only if the usage is documented in comments or configuration with justification.
- **Detail on fail:** `"X directives contain unsafe-eval: script-src, worker-src"` or `"script-src includes 'unsafe-eval' — enables eval(), Function(), and string-based setTimeout/setInterval"`
- **Remediation:** `'unsafe-eval'` re-enables JavaScript's most dangerous features. Most modern libraries work without it. If a library requires eval:

  1. Check if a newer version has removed the dependency on eval
  2. If unavoidable, isolate the eval-requiring code in a Web Worker with its own restricted CSP
  3. As a last resort, scope `'unsafe-eval'` to only `script-src` and document the justification

  ```
  # Preferred: no unsafe-eval
  script-src 'nonce-abc123' 'strict-dynamic'
  ```

## External references

- cwe CWE-79
- cwe CWE-693
- owasp A03

Taxons: injection-and-input-trust

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