Content Security Policy (CSP) — A Complete Configuration Guide
Content Security Policy (CSP) is a security header that tells the browser which sources are allowed to load resources: scripts, styles, images, fonts, frames, and more. CSP is one of the most powerful tools for defending against XSS attacks (Cross-Site Scripting), code injection, and clickjacking.
Why You Need CSP
XSS remains one of the most common web vulnerabilities according to the OWASP Top 10. Even with careful input filtering, there is a risk of missing an attack vector. CSP acts as the last line of defense: even if an attacker injects malicious code, the browser won't execute it if the source isn't allowed by the policy.
What CSP protects against:
- XSS attacks — blocks execution of inline scripts and loading scripts from unauthorized domains
- Data injection — prevents loading content from unexpected sources
- Clickjacking — the frame-ancestors directive controls who can embed your site in an iframe
- Mixed content — blocks HTTP resources on SSL/TLS проверку pages
- Data exfiltration — limits domains where data can be sent (connect-src, form-action)
CSP Syntax
CSP is delivered via an HTTP header:
Content-Security-Policy: directive-1 value1 value2; directive-2 value3;
Each directive controls a specific type of resource:
| Directive | Controls | Example |
|---|---|---|
default-src | Fallback for all resource types | default-src 'self' |
script-src | JavaScript | script-src 'self' cdn.example.com |
style-src | CSS | style-src 'self' 'unsafe-inline' |
img-src | Images | img-src 'self' data: https: |
font-src | Fonts | font-src 'self' fonts.gstatic.com |
connect-src | AJAX, WebSocket, Fetch | connect-src 'self' api.example.com |
frame-src | Iframe sources | frame-src youtube.com |
frame-ancestors | Who can embed you in an iframe | frame-ancestors 'none' |
form-action | Where forms can submit | form-action 'self' |
base-uri | Restriction for <base> tag | base-uri 'self' |
object-src | Flash, Java applets | object-src 'none' |
Source Values
| Value | Description |
|---|---|
'self' | Same origin only |
'none' | Block everything |
'unsafe-inline' | Allow inline code (reduces protection) |
'unsafe-eval' | Allow eval() (reduces protection) |
'nonce-abc123' | Allow elements with the specified nonce |
'strict-dynamic' | Trust scripts loaded by trusted scripts |
https: | Any HTTPS source |
data: | Data URIs (e.g., data:image/png) |
*.example.com | Any subdomain of example.com |
CSP Configuration Examples
Basic Policy
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; object-src 'none'
Site with Google Analytics and Fonts
Content-Security-Policy: default-src 'self'; script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https://www.google-analytics.com; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://www.google-analytics.com; frame-ancestors 'none'
Strict Policy with Nonce
Content-Security-Policy: default-src 'self'; script-src 'nonce-rAnd0mVaLu3' 'strict-dynamic'; style-src 'self' 'nonce-rAnd0mVaLu3'; object-src 'none'; base-uri 'self'
When using nonce, each <script> and <style> tag must include the attribute:
<script nonce="rAnd0mVaLu3">
// This script will execute
</script>
Report-Only Mode
Before enabling CSP in production, use report-only mode:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /api/csp-report
In this mode, the browser doesn't block resources but only sends JSON reports about violations. This lets you identify all third-party resources before enforcing restrictions.
Step-by-Step CSP Deployment
- Check your current security headers using the enterno.io HTTP header checker
- Compile a list of all third-party resources on your site (analytics, fonts, CDN, widgets)
- Create a policy in Report-Only mode
- Monitor violation reports for 1–2 weeks
- Add missing sources to the policy
- Enable CSP in enforcement mode
- Continue monitoring reports
Common Mistakes
- unsafe-inline and unsafe-eval — negate XSS protection. Use nonce or hash when possible
- Overly broad policy —
script-src *ordefault-src *provide no real protection - Missing default-src — without a fallback, new resource types can load from anywhere
- Skipping Report-Only testing — enabling CSP without testing can break your site
- Ignoring frame-ancestors — without it, your site remains vulnerable to clickjacking
- Not updating the policy — when adding new integrations, CSP must be updated
CSP and Performance
CSP not only improves security but can also positively impact performance:
- Blocking unwanted scripts from browser extensions
- Preventing loading of malicious cryptocurrency miners
- Limiting network requests to external domains
Checking CSP
Use the enterno.io HTTP header checker to analyze your site's current CSP policy. The tool will show the Content-Security-Policy header and help identify its absence.
Browser developer tools are also useful: the Console tab will show all CSP violations with detailed information about blocked resources.
Check your website right now
Check now →