← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Content Security Policy (CSP)

Security PHP 5.0+ Intermediate
debt(d3/e5/b5/t7)
d3 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'default linter catches the common case' (d3). The term's detection_hints.tools list includes lighthouse, owasp-zap, and csp-evaluator — these are mainstream security/quality scanners that will flag missing CSP headers or dangerous directives like unsafe-inline. Not quite d1 since it's not a compile-time error, but readily caught by common web security tooling.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix suggests starting with a restrictive policy and adding nonces for inline scripts. While setting the header itself is one line, actually implementing nonces across all inline scripts requires touching every template/view that has inline JS, and potentially refactoring JavaScript to external files. For legacy applications with scattered inline scripts, this is a significant refactor.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). CSP applies to all web contexts and becomes a persistent consideration — every new script source, inline handler, or third-party integration must be evaluated against the policy. Developers must remember to add nonces, update the policy for new CDNs, and maintain awareness of what sources are allowed. It's not quite b7 (doesn't shape every change), but it's a tax on frontend work indefinitely.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field explicitly states that developers believe 'unsafe-inline still meaningfully prevents XSS' when in fact it defeats the primary purpose of CSP entirely. This is a serious trap because the policy appears to be working (header is set, no errors), but provides essentially no XSS protection. Developers familiar with other security headers may assume presence equals protection, contradicting how CSP actually requires strict configuration to be effective.

About DEBT scoring →

Also Known As

CSP Content-Security-Policy header

TL;DR

An HTTP response header that restricts which scripts, styles, and resources the browser is allowed to load.

Explanation

CSP is a defence-in-depth measure against XSS. By declaring a policy via the Content-Security-Policy header, you tell the browser to refuse executing inline scripts, loading scripts from untrusted domains, or evaluating eval(). Even if an attacker injects a script tag, CSP prevents it from running. A strict CSP (script-src 'nonce-{random}') is the most effective configuration. CSP does not replace output encoding — it is an additional layer.

Diagram

flowchart TD
    PAGE[Page served with CSP header] --> BROWSER3[Browser enforces policy]
    BROWSER3 --> SCRIPTS{Script source allowed?}
    SCRIPTS -->|from own domain| ALLOW3[Execute]
    SCRIPTS -->|inline script tag| BLOCK3[Block - no unsafe-inline]
    SCRIPTS -->|from cdn example.com| CHECK3{In script-src?}
    CHECK3 -->|yes| ALLOW3
    CHECK3 -->|no| BLOCK3
    subgraph Directives
        DEFAULT[default-src self]
        SCRIPT[script-src self nonce-xyz]
        STYLE[style-src self unsafe-inline]
        IMG[img-src self data blob]
    end
style ALLOW3 fill:#238636,color:#fff
style BLOCK3 fill:#f85149,color:#fff

Common Misconception

A CSP with unsafe-inline still meaningfully prevents XSS. unsafe-inline defeats the primary purpose of CSP by allowing all inline scripts — a meaningful CSP requires nonces or hashes instead.

Why It Matters

CSP is the primary browser-enforced defence against XSS — it restricts which scripts can execute, where resources load from, and prevents inline script injection even if an XSS vulnerability exists.

Common Mistakes

  • Using unsafe-inline in the script-src directive — negates XSS protection entirely.
  • Using unsafe-eval — allows string-to-code execution which attackers can exploit.
  • An overly permissive default-src: * that effectively disables source restrictions.
  • Not deploying CSP at all, relying solely on output encoding which may have gaps.

Avoid When

  • Setting unsafe-inline or unsafe-eval — these negate the XSS protection that CSP exists to provide.
  • Deploying CSP in enforce mode before testing in report-only mode — you will break legitimate functionality.
  • Using wildcard (*) sources for script-src — a wildcard allows loading scripts from any origin.
  • Setting CSP only on the HTML page but not on API responses that return HTML fragments.

When To Use

  • Any web application that renders user-supplied content — CSP is the last line of defence against XSS.
  • Applications with a well-defined set of trusted script, style, and media sources.
  • After completing XSS remediation — CSP reduces the blast radius of any XSS that slips through.
  • Report-only mode first, to identify violations before enforcing.

Code Examples

✗ Vulnerable
// Overly permissive CSP that provides no XSS protection:
header("Content-Security-Policy: default-src *; script-src * 'unsafe-inline' 'unsafe-eval'");
✓ Fixed
// Tight CSP — no inline scripts, only own domain + CDN
header("Content-Security-Policy: " .
    "default-src 'self'; " .
    "script-src 'self' https://cdn.jsdelivr.net; " .
    "style-src  'self' 'unsafe-inline'; " .
    "img-src    'self' data: https:; " .
    "font-src   'self'; " .
    "connect-src 'self' https://api.yourapp.com; " .
    "frame-ancestors 'none'; " .
    "base-uri 'self'; " .
    "form-action 'self';"
);

// Start in report-only mode to detect breakage before enforcing:
header('Content-Security-Policy-Report-Only: ...; report-uri /csp-report');

Added 15 Mar 2026
Edited 25 Mar 2026
Views 77
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 2 pings T 3 pings F 2 pings S 5 pings S 3 pings M 2 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 2 pings T 0 pings W
No pings yet today
PetalBot 1 SEMrush 1
Scrapy 17 Amazonbot 10 Perplexity 7 Ahrefs 6 Google 4 Unknown AI 3 ChatGPT 3 SEMrush 3 Claude 2 Meta AI 1 Sogou 1 PetalBot 1
crawler 53 crawler_json 4 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: High
⚡ Quick Fix
Start with Content-Security-Policy: default-src 'self'; then add specific allowances per resource type — use nonces for inline scripts rather than 'unsafe-inline'
📦 Applies To
PHP 5.0+ web
🔗 Prerequisites
🔍 Detection Hints
Missing CSP header; CSP with unsafe-inline unsafe-eval wildcard * sources; no nonce on inline scripts
Auto-detectable: ✓ Yes lighthouse owasp-zap csp-evaluator
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✗ Manual fix Fix: Medium Context: File
CWE-79 CWE-693


✓ schema.org compliant