Content-Security-Policy header example
Complete guide to implementing Content Security Policy (CSP) headers for website security.
What is CSP?
Content Security Policy is a security header that helps prevent Cross-Site Scripting (XSS), clickjacking, and other code injection attacks by specifying which content sources are trusted.
Basic Example
Header always set Content-Security-Policy "default-src 'self'"
This allows resources only from your own domain.
Comprehensive Example
Header always set Content-Security-Policy "default-src 'none'; script-src 'self'; style-src 'self'; img-src data: 'self'; connect-src 'self'; font-src 'self'; object-src 'none'; media-src 'self'; frame-src 'none'; frame-ancestors 'none'; form-action 'self'; manifest-src 'self'; base-uri 'none'; upgrade-insecure-requests;"
Directive Breakdown
default-src 'none'
Blocks all content by default. You must then explicitly allow each content type.
script-src 'self'
Allow JavaScript only from your own domain.
Example allowing specific domains:
script-src 'self' https://cdnjs.cloudflare.com https://code.jquery.com
style-src 'self'
Allow CSS only from your domain.
Example with Google Fonts:
style-src 'self' https://fonts.googleapis.com
img-src data: 'self'
Allow images from your domain and inline data URLs (base64).
Example with CDN:
img-src 'self' data: https://cdn.example.com
font-src 'self'
Allow fonts from your domain.
Example with Google Fonts:
font-src 'self' https://fonts.gstatic.com
connect-src 'self'
Allow AJAX, WebSocket, and EventSource connections to your domain.
frame-src 'self'
Allow iframes from your domain.
Example with trusted embeds:
frame-src 'self' https://www.youtube.com https://player.vimeo.com
frame-ancestors 'none'
Prevent your site from being embedded in iframes (clickjacking protection).
form-action 'self'
Allow forms to submit only to your domain.
object-src 'none'
Block Flash and other plugins.
media-src 'self'
Allow audio/video from your domain.
manifest-src 'self'
Allow web app manifests from your domain.
base-uri 'none'
Prevent manipulation of the <base> tag.
upgrade-insecure-requests
Automatically upgrades HTTP requests to HTTPS.
Real-World Examples
Static Website
Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; upgrade-insecure-requests;
Website with Google Analytics & Fonts
Content-Security-Policy: default-src 'self'; script-src 'self' https://www.google-analytics.com https://ssl.google-analytics.com; style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https://www.google-analytics.com; connect-src 'self' https://www.google-analytics.com;
Website with YouTube Embeds
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; frame-src https://www.youtube.com; upgrade-insecure-requests;
E-commerce with Payment Gateway
Content-Security-Policy: default-src 'self'; script-src 'self' https://js.stripe.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; frame-src https://js.stripe.com; connect-src 'self' https://api.stripe.com;
Testing Your CSP
Report-Only Mode
Test without blocking:
Header always set Content-Security-Policy-Report-Only "default-src 'self'; report-uri /csp-report"
View Violations in Browser Console
Open DevTools (F12) → Console tab to see CSP violations.
Online Tools
Common Issues & Solutions
Inline Scripts Blocked
Problem: script-src 'self' blocks inline <script> tags.
Solution 1: Move scripts to external files.
Solution 2: Use nonces (advanced):
script-src 'self' 'nonce-random123'
Inline Styles Blocked
Problem: Inline style="" attributes blocked.
Solution: Move styles to CSS files.
Images from Other Domains
Problem: CDN images blocked.
Solution:
img-src 'self' https://cdn.example.com
Implementation
Apache (.htaccess)
<IfModule mod_headers.c>
Header always set Content-Security-Policy "default-src 'none'; script-src 'self'; style-src 'self'; img-src data: 'self'; font-src 'self'; upgrade-insecure-requests;"
</IfModule>
Nginx
add_header Content-Security-Policy "default-src 'none'; script-src 'self'; style-src 'self'; img-src data: 'self'; font-src 'self'; upgrade-insecure-requests;" always;
PHP
header("Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self';");
CSP with Nonces (Advanced)
Generate unique nonces for each request:
<?php
$nonce = base64_encode(random_bytes(16));
header("Content-Security-Policy: script-src 'self' 'nonce-$nonce'; style-src 'self' 'nonce-$nonce';");
?>
<script nonce="<?php echo $nonce; ?>">
console.log("This script is allowed");
</script>
Monitoring Violations
Set up Reporting Endpoint
Content-Security-Policy: default-src 'self'; report-uri https://your-domain.com/csp-report;
Example Report Handler (PHP)
<?php
$data = file_get_contents('php://input');
$report = json_decode($data, true);
file_put_contents('csp-reports.log', print_r($report, true), FILE_APPEND);
?>
Best Practices
- Start with Report-Only - Test before enforcing
- Be Specific - Don't use
'unsafe-inline'or'unsafe-eval'unless absolutely necessary - Use HTTPS - CSP works best with HTTPS
- Monitor Reports - Set up violation reporting
- Update Gradually - Add directives as needed
Security Rating Impact
Implementing CSP can improve your score on:
Related Headers
- Content-Security-Policy-Report-Only - Test mode
- X-Content-Type-Options - Prevent MIME sniffing
- X-Frame-Options - Clickjacking protection (legacy)
Additional Resources
- MDN CSP Documentation
- CSP Quick Reference
- Test your site: SecurityHeaders.nl