Inspecteur CSP
Analysez les directives CSP pour faiblesses de sécurité et recommandations renforcées
What is Content Security Policy Inspection?
Content Security Policy (CSP) inspection is the systematic analysis of deployed CSP headers to identify security weaknesses, overly permissive directives, and misconfigurations that undermine the policy's protective intent. While a CSP generator builds new policies from scratch, an inspector evaluates existing policies — detecting gaps that allow cross-site scripting (XSS), data exfiltration, clickjacking, and other injection attacks to bypass what appears to be a secure configuration.
A CSP header that exists but is poorly configured provides a false sense of security. Many production
deployments contain directives with 'unsafe-inline', 'unsafe-eval', wildcard
sources (*), or overly broad domain allowlists that effectively neutralize the policy's
protection. The CSP Inspector parses raw headers, scores each directive against established security
criteria, and produces actionable findings that prioritize remediation by attack surface impact.
Security Scoring Methodology
The CSP Inspector assigns a security score from 0 to 100 based on a weighted evaluation of each directive present in the policy. The scoring model considers three dimensions: directive coverage (are all critical directives defined?), source restrictiveness (how narrowly scoped is each directive?), and bypass resistance (can known attack techniques circumvent the policy?).
-
Critical deductions (−20 to −30 points): Presence of
'unsafe-inline'inscript-src(negates XSS protection entirely),'unsafe-eval'allowingeval()/Function()execution, wildcard (*) indefault-srcorscript-src, and missingscript-srcdirective whendefault-srcis also permissive. -
High deductions (−10 to −15 points): Use of
data:URIs in script or object sources (enables inline payload injection), overly broad CDN domains that host user-uploaded content (e.g.,*.googleapis.comwithout path restriction), missingobject-srcdirective (defaults todefault-srcwhich may be permissive), and absentbase-uriallowing base tag injection attacks. -
Medium deductions (−5 to −8 points): Missing
frame-ancestors(clickjacking vulnerability), absentform-action(form hijacking), noupgrade-insecure-requestson HTTPS sites, and use ofreport-uri(deprecated) instead ofreport-to. -
Positive scoring (+5 to +10 points): Use of nonce-based or hash-based script
allowlisting (
'nonce-...','sha256-...'), presence of'strict-dynamic'for trust propagation, inclusion ofrequire-trusted-types-for 'script', and complete directive coverage across all resource types.
A score of 80+ indicates a well-configured policy suitable for production enforcement. Scores between 50-79 suggest the policy provides partial protection but has exploitable gaps. Below 50, the policy is effectively security theater — present but not protective.
Common CSP Misconfigurations and Bypass Techniques
The inspector detects misconfigurations that create exploitable attack surfaces, including bypass techniques documented by security researchers and used in real-world penetration testing:
-
JSONP endpoint bypass: When a CSP allows a domain that hosts JSONP endpoints
(e.g.,
accounts.google.com), attackers can execute arbitrary JavaScript via<script src="https://accounts.google.com/o/oauth2/revoke?callback=alert(1)">. The inspector maintains a database of known JSONP-capable domains and flags their inclusion inscript-src. -
CDN-hosted attacker scripts: Allowing broad CDN domains like
*.cloudflare.com,*.amazonaws.com, or*.jsdelivr.netenables attackers to host malicious payloads on the same CDN and load them within the CSP allowlist. The inspector identifies CDN wildcards and recommends path-specific restrictions or hash-based integrity checks. - Open redirect via allowed origins: If a CSP-allowed domain has an open redirect vulnerability, attackers can chain it to load scripts from arbitrary origins while appearing to originate from the trusted domain. The inspector flags domains known to have redirect endpoints and warns about transitive trust implications.
-
Angular/Vue template injection: Policies that allow
'unsafe-eval'combined with framework CDN sources enable template injection attacks. Attackers inject expressions like{{constructor.constructor('alert(1)')()}} that frameworks evaluate without triggering traditional XSS filters. The inspector detects framework CDN + unsafe-eval combinations. -
Base URI hijacking: Without
base-uri 'self'orbase-uri 'none', attackers can inject a<base href="https://evil.com">tag that redirects all relative URL script loads to an attacker-controlled server — bypassingscript-srcrestrictions entirely.
Each finding includes the specific directive responsible, the attack vector it enables, and a concrete remediation step that preserves application functionality while closing the security gap.
Directive Evaluation: Permissive vs Restrictive
The inspector classifies each directive source on a restrictiveness spectrum. Understanding this classification helps developers interpret audit results and prioritize fixes:
-
Maximally restrictive:
'none'— blocks all resources of that type. Ideal forobject-src,base-uri, and any resource type your application does not use. -
Highly restrictive:
'self'combined with nonce-based or hash-based script allowlisting. Also includes'strict-dynamic'which propagates trust only to scripts explicitly loaded by already-trusted scripts, eliminating the need for domain allowlists. -
Moderately restrictive: Specific domain allowlists with exact origins
(e.g.,
https://cdn.example.com) — acceptable when nonce/hash approaches are impractical, but each domain increases the attack surface proportionally to that domain's security posture. -
Weakly restrictive: Wildcard subdomains (
*.example.com), protocol schemes (https:), anddata:URIs — each provides minimal restriction.https:allows any HTTPS origin globally.data:enables inline payload injection in base64-encoded form. -
Non-restrictive (nullifying):
'unsafe-inline','unsafe-eval', and bare*— these effectively disable CSP protection for the directive they appear in.'unsafe-inline'inscript-srcallows any injected<script>tag to execute, which is precisely the attack vector CSP was designed to prevent.
The inspector computes a per-directive restrictiveness grade (A through F) and highlights directives where upgrading to a more restrictive source expression would meaningfully reduce attack surface without breaking application functionality.
Report-Only Mode Analysis and Enforcement Migration
The Content-Security-Policy-Report-Only header allows deploying a CSP in observation
mode — violations generate reports but resources are not blocked. The inspector analyzes report-only
policies differently from enforcing ones, providing migration guidance for transitioning to full
enforcement:
-
Report-only adequacy check: Verifies that the report-only policy includes a
report-toorreport-uridirective. A report-only policy without reporting endpoints generates no violation data and serves no purpose — it is effectively dead code in your HTTP response headers. - Enforcement readiness assessment: Compares the report-only policy against the page's actual resource loading patterns (if provided) to estimate how many legitimate resources would be blocked upon enforcement. A policy that would block critical application scripts is not ready for enforcement regardless of its security score.
-
Incremental tightening recommendations: Suggests a phased migration path from
the current report-only policy to a strict enforcing policy. For example: start by enforcing
object-src 'none'andbase-uri 'self'(low breakage risk), then migratescript-srcfrom domain allowlist to nonce-based (medium effort), and finally add'strict-dynamic'to eliminate the allowlist entirely (requires build pipeline integration for nonce injection). -
Dual-header detection: Identifies when both
Content-Security-PolicyandContent-Security-Policy-Report-Onlyare present simultaneously. When both exist, the enforcing header takes precedence for blocking while the report-only header can test a stricter future policy. The inspector validates that the report-only policy is strictly equal to or more restrictive than the enforcing one — if the report-only policy is weaker, it provides no useful migration data.
Code Examples
CSP Header Parsing and Security Evaluation
// CSP Inspector — parse header and evaluate security posture
function inspectCsp(headerValue) {
const directives = {};
const findings = [];
let score = 100;
// Parse CSP header into directive map
headerValue.split(';').forEach(part => {
const trimmed = part.trim();
if (!trimmed) return;
const [name, ...sources] = trimmed.split(/\s+/);
directives[name] = sources;
});
// Check: missing critical directives
const critical = ['script-src', 'object-src', 'base-uri'];
for (const dir of critical) {
if (!directives[dir] && !directives['default-src']) {
findings.push({
severity: 'high',
directive: dir,
issue: `Missing "${dir}" directive with no default-src fallback`,
fix: `Add ${dir} with restrictive sources (e.g., 'self' or 'none')`
});
score -= 15;
}
}
// Check: unsafe-inline in script-src (nullifies XSS protection)
const scriptSrc = directives['script-src'] || directives['default-src'] || [];
if (scriptSrc.includes("'unsafe-inline'")) {
findings.push({
severity: 'critical',
directive: 'script-src',
issue: "'unsafe-inline' allows any injected script to execute",
fix: "Replace with nonce-based ('nonce-<random>') or hash-based allowlisting"
});
score -= 30;
}
// Check: unsafe-eval allows eval()/Function() execution
if (scriptSrc.includes("'unsafe-eval'")) {
findings.push({
severity: 'critical',
directive: 'script-src',
issue: "'unsafe-eval' enables eval()-based XSS attacks",
fix: "Remove 'unsafe-eval' and refactor code to avoid eval/Function/setTimeout(string)"
});
score -= 25;
}
// Check: wildcard source in script-src
if (scriptSrc.includes('*')) {
findings.push({
severity: 'critical',
directive: 'script-src',
issue: "Wildcard '*' allows scripts from any origin",
fix: "Replace with specific domain allowlist or 'strict-dynamic' with nonces"
});
score -= 30;
}
// Check: data: URI in script sources (inline payload injection)
if (scriptSrc.includes('data:')) {
findings.push({
severity: 'high',
directive: 'script-src',
issue: "'data:' allows base64-encoded script injection",
fix: "Remove 'data:' from script-src; use nonces for inline scripts"
});
score -= 15;
}
// Check: missing frame-ancestors (clickjacking)
if (!directives['frame-ancestors']) {
findings.push({
severity: 'medium',
directive: 'frame-ancestors',
issue: "Missing frame-ancestors — page can be framed (clickjacking)",
fix: "Add frame-ancestors 'self' or 'none' to prevent framing"
});
score -= 8;
}
// Classify directive restrictiveness
const grades = {};
for (const [dir, sources] of Object.entries(directives)) {
if (sources.includes("'none'")) grades[dir] = 'A';
else if (sources.includes("'strict-dynamic'")) grades[dir] = 'A';
else if (sources.every(s => s === "'self'" || s.startsWith("'nonce-")
|| s.startsWith("'sha256-"))) grades[dir] = 'B';
else if (sources.some(s => s === '*' || s === "'unsafe-inline'")) grades[dir] = 'F';
else grades[dir] = 'C';
}
return {
score: Math.max(0, score),
directives,
findings,
grades,
hasReportOnly: false,
directiveCount: Object.keys(directives).length
};
}
// Example: inspect a weak CSP header
const result = inspectCsp(
"default-src 'self'; script-src 'self' 'unsafe-inline' https:; style-src * 'unsafe-inline'"
);
// → { score: 35, findings: [{severity: 'critical', issue: "'unsafe-inline' allows..."}], ... }Standards & Specifications
- W3C Content Security Policy Level 3 — Current CSP specification defining directives, source expressions, violation reporting, and enforcement behavior
- W3C CSP Level 2 — Previous stable CSP specification — still the baseline for browser compatibility and widely deployed policies
- MDN Content-Security-Policy Reference — Comprehensive directive reference with browser compatibility tables and usage examples