Skip to content
DevMarDe
Crawl Audit check 149Crawl AuditSecurity

Content-Security-Policy: Crawl Audit check 149

Crawl Audit check 149 looks for a Content-Security-Policy header. What a CSP blocks, how to roll one out in report-only mode first, and why ours isn't set yet.

Zain Kazmi2 min read
On this page
Check
149 of 200
Module
Security & Infrastructure
Group
HTTP Security Headers
Impact
Medium

Short answer: a Content-Security-Policy lists where your page may load scripts, styles and other files from, so code injected by an attacker is blocked. It's the main browser-side defence against cross-site scripting, and the hardest security header to get right. Check 149 passes if any CSP header is present.

What Crawl Audit checks

  • Pass: a Content-Security-Policy header, with any value. The report shows its first 120 characters.
  • Fail: none.

A weak policy passes as easily as a strict one, and a policy set only in a <meta> tag or only as Report-Only isn't counted. Check 164 looks at whether your policy allows inline scripts.

What the sources say

  • MDN: CSP "is mainly used as a defense against cross-site scripting (XSS) attacks, in which an attacker is able to inject malicious code into the victim's site."
  • OWASP: "Using the Content-Security-Policy-Report-Only, you can deliver a CSP that doesn't get enforced."
  • OWASP also: "CSP should not be relied upon as the only defensive mechanism against XSS." Escaping user input properly comes first.

Rolling one out

  1. List what your pages really load: your own files, analytics, fonts, embeds, payment widgets.
  2. Send it as Content-Security-Policy-Report-Only and watch the browser console and any reports for a week.
  3. Fix or allow what breaks, then switch to the enforcing header.
  4. Prefer nonces or hashes over 'unsafe-inline' for scripts.
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://analytics.example.com; object-src 'none'; base-uri 'self'; frame-ancestors 'self'

On devmarde.com

We don't send a CSP yet, so this check fails for us. Our site is built with Next.js, whose docs say: "When you use nonces in your CSP, all pages must be dynamically rendered." Our pages are prebuilt for speed, and the option that keeps them prebuilt (hash-based, using Subresource Integrity) is marked experimental by Next.js. We haven't chosen between the two yet, and we'd rather say so than ship a policy that only exists to pass this check.

Sources

All 200 Crawl Audit checks

See how your site does on every check.

Crawl Audit runs this check and 199 others on your domain. The full report is $7.89, one time. The free check on this site covers 25.