Content Security Policy headers are supposed to be the last line of defense against cross-site scripting. In practice, most CSP headers are so broad they might as well not exist.
The pattern is almost always the same. A developer writes a strict CSP. Then marketing adds a chat widget. Then someone embeds a YouTube video. Then the ad team needs a pixel. Each addition loosens the policy until the header reads something like script-src 'self' *.googleapis.com *.gstatic.com *.facebook.net *.doubleclick.net 'unsafe-inline' and at that point you've told the browser to trust scripts from four of the largest ad networks on the internet, plus any inline script an attacker can inject.
The gap between policy and reality
A CSP header is a declaration of intent. It says "only load resources from these sources." But nobody audits whether the sources listed in the policy actually match what the page loads.
Two things go wrong:
Over-permissive entries. Your CSP allows *.cdn.example.com but your page only loads from assets.cdn.example.com. The wildcard lets an attacker host a malicious script on evil.cdn.example.com and your browser will execute it without complaint.
Missing entries. Your page loads a script from a domain not covered by the CSP. The browser blocks it, but you don't notice because CSP violations are silent by default unless you've configured report-to. Meanwhile, your chat widget is broken in production and nobody knows.
What the tool does
The CSP Allowlist Completeness Audit fetches your page, reads the CSP header (or meta tag), then inventories every script, stylesheet, iframe, image, font, and connect-src your page actually loads. It cross-references the two lists.
Resources your page loads but your CSP doesn't cover get flagged as gaps. CSP entries that cover sources your page doesn't load get flagged as over-broad. Wildcard domains get special attention because they're the most common vector for CSP bypasses.
The result is a gap analysis, not a pass/fail grade. You might have legitimate reasons for broad entries. But you should know they're there, and you should know exactly which resources rely on them.
Why this matters beyond security
A tight CSP is also a performance and privacy signal. Every domain in your CSP is a domain your page is allowed to contact. If your CSP lists 15 external domains, that's 15 potential third-party connections your visitors' browsers will make. Each one is a DNS lookup, a TLS handshake, and a data leak of your visitor's IP and referrer.
Tightening your CSP often reveals dependencies you forgot about. That analytics pixel someone added in 2023 and never removed. The A/B testing script that's been loading but nobody reads the reports from. The CDN you migrated away from six months ago but left in the header.
If you're building sites for clients and want a framework for keeping the dependency list short from day one, The $20 Dollar Agency covers the lean-stack approach.
Fact-check notes and sources
- CSP bypass via wildcard subdomains: documented in Google's CSP Evaluator research (research.google/pubs/pub45542)
- CSP report-to directive: W3C CSP Level 3 specification, Section 10
- 'unsafe-inline' effectively disables XSS protection for scripts: MDN CSP script-src documentation
Related reading
- CSP strictness: nonce, hash, and strict-dynamic
- Trusted Types and DOM XSS prevention
- Inline event handlers break strict CSP
- Subresource Integrity on external scripts
This post is informational, not security-consulting advice. Mentions of Google, MDN, and W3C are nominative fair use. No affiliation is implied.