Deploying CSP Policies
Once your policy is validated, deploy it to your web server. This guide covers deployment methods for common platforms.
Before Deploying
Before deploying your CSP policy:
- ✅ Run a validation scan and ensure it passes
- ✅ Start with report-only mode to monitor violations
- ✅ Have a rollback plan (keep your old configuration)
- ✅ Test on a staging environment first if possible
Required Headers for Violation Reporting
Important: To receive CSP violation reports from all browsers, you need to set two headers:
- Content-Security-Policy - Contains your policy with
report-uriandreport-todirectives (for Firefox, Safari, and as fallback) - Reporting-Endpoints - Defines the endpoint group for the Reporting API (required by Chrome, Edge, Brave)
Browser Support for CSP Reporting
| Browser | Reporting Mechanism | Required Headers |
|---|---|---|
| Chrome, Edge, Brave | report-to (Reporting API v1) | Both CSP + Reporting-Endpoints |
| Firefox | report-uri (legacy) | CSP only |
| Safari | report-uri (legacy) | CSP only |
The Reporting-Endpoints Header
This header defines named endpoints that report-to references. ScriptAttest policies use the endpoint group name csp-endpoint:
Reporting-Endpoints: csp-endpoint="https://scriptattest.com/api/csp/report/YOUR_TOKEN"
Replace YOUR_TOKEN with your site's report token (found in your dashboard under Violations tab).
Deployment Methods
1. HTTP Header (Recommended)
The most secure and recommended method is to set the CSP via HTTP headers. This prevents the policy from being modified by client-side code.
Nginx
Add both headers in your Nginx configuration:
server {
listen 80;
server_name example.com;
# Required for Chrome/Edge/Brave violation reporting
add_header Reporting-Endpoints 'csp-endpoint="https://scriptattest.com/api/csp/report/YOUR_TOKEN"' always;
# Your CSP policy (includes both report-to and report-uri)
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; ... report-to csp-endpoint; report-uri https://scriptattest.com/api/csp/report/YOUR_TOKEN" always;
} For report-only mode:
add_header Content-Security-Policy-Report-Only "default-src 'self'; ..." always; Apache
Add both headers in your Apache configuration or .htaccess:
<IfModule mod_headers.c>
# Required for Chrome/Edge/Brave violation reporting
Header set Reporting-Endpoints "csp-endpoint=\"https://scriptattest.com/api/csp/report/YOUR_TOKEN\""
# Your CSP policy
Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; ... report-to csp-endpoint; report-uri https://scriptattest.com/api/csp/report/YOUR_TOKEN"
</IfModule> Cloudflare
In Cloudflare dashboard, add both headers via Transform Rules:
- Go to Rules → Transform Rules → Modify Response Header
- Create a new rule
- Add header:
Reporting-Endpointswith value:csp-endpoint="https://scriptattest.com/api/csp/report/YOUR_TOKEN" - Add header:
Content-Security-Policywith your policy string
Vercel
Add both headers in vercel.json:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Reporting-Endpoints",
"value": "csp-endpoint=\"https://scriptattest.com/api/csp/report/YOUR_TOKEN\""
},
{
"key": "Content-Security-Policy",
"value": "default-src 'self'; script-src 'self' https://cdn.example.com; ... report-to csp-endpoint; report-uri https://scriptattest.com/api/csp/report/YOUR_TOKEN"
}
]
}
]
} Netlify
Add both headers in _headers file:
/*
Reporting-Endpoints: csp-endpoint="https://scriptattest.com/api/csp/report/YOUR_TOKEN"
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; ... report-to csp-endpoint; report-uri https://scriptattest.com/api/csp/report/YOUR_TOKEN Express.js (Node.js)
Add custom middleware for both headers:
const express = require('express');
const app = express();
const REPORT_TOKEN = 'YOUR_TOKEN';
const REPORT_URL = `https://scriptattest.com/api/csp/report/${REPORT_TOKEN}`;
// Add both headers for all responses
app.use((req, res, next) => {
// Reporting-Endpoints for Chrome/Edge/Brave
res.setHeader('Reporting-Endpoints', `csp-endpoint="${REPORT_URL}"`);
// CSP with both report-to and report-uri
res.setHeader('Content-Security-Policy',
"default-src 'self'; script-src 'self' https://cdn.example.com; " +
`report-to csp-endpoint; report-uri ${REPORT_URL}`
);
next();
});
Or with the helmet middleware (note: you'll still need to add Reporting-Endpoints separately):
const helmet = require('helmet');
app.use((req, res, next) => {
res.setHeader('Reporting-Endpoints', `csp-endpoint="${REPORT_URL}"`);
next();
});
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.example.com"],
reportTo: ["csp-endpoint"],
reportUri: [REPORT_URL],
},
},
})); Django (Python)
Use django-csp middleware:
# settings.py
MIDDLEWARE = [
'csp.middleware.CSPMiddleware',
# ... other middleware
]
CSP_DEFAULT_SRC = ["'self'"]
CSP_SCRIPT_SRC = ["'self'", "https://cdn.example.com"]
# ... other directives 2. HTML Meta Tag (Not Recommended)
You can also set CSP via a meta tag in your HTML, but this is less secure:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://cdn.example.com; ..."> Warning: Meta tags can be modified by client-side code and don't support the report-uri directive. Use HTTP headers when possible.
Deployment Workflow
Recommended deployment workflow:
- Deploy in report-only mode - Monitor for violations without blocking
- Monitor for 24-48 hours - Check violation reports and fix any issues
- Approve missing sources - Add any legitimate sources that were missed
- Regenerate and redeploy - Update the policy with new sources
- Switch to enforce mode - Once confident, switch from report-only to enforce
Updating Policies
When you need to update your policy:
- Approve or reject new sources in ScriptAttest
- Regenerate the policy
- Run a validation scan
- Update the header value on your server
- Reload your web server configuration
Testing Deployment
After deploying, verify the policy is active:
- Browser DevTools - Check Network tab → Headers → Response Headers
- curl -
curl -I https://example.com | grep -i content-security-policy - Online tools - Use securityheaders.com or similar to verify
Rollback Plan
If something goes wrong:
- Keep your old configuration backed up
- Have a way to quickly remove or modify the header
- Consider using report-only mode initially
- Monitor your site's error logs after deployment
Common Issues
Policy Not Applied
Problem: CSP header not showing up in browser.
Solutions:
- Check web server configuration syntax
- Ensure header module is enabled (Apache)
- Clear browser cache
- Check for conflicting headers
Site Breaks After Deployment
Problem: Resources are blocked and site doesn't work.
Solutions:
- Switch to report-only mode immediately
- Check violation reports to identify missing sources
- Approve missing sources and regenerate
- Consider temporarily allowing more permissive policy
Best Practices
- Use HTTP headers - More secure than meta tags
- Start with report-only - Monitor before enforcing
- Test thoroughly - Validate before deploying
- Monitor violations - Check reports regularly
- Keep policies updated - Regenerate when adding features
- Document changes - Note why sources were approved
Next Steps
After deploying:
- Monitor violations in your dashboard
- Review violation reports and fix issues
- Switch to enforce mode once confident
- Set up scheduled scans for ongoing monitoring