Add a Content-Security-Policy header
headers-csp
A Content-Security-Policy tells the browser which scripts it is allowed to run, so markup an attacker manages to inject never executes.
CDN and edge
Web servers
Frameworks
Cloudflare
- 1 Go to Rules > Transform Rules > Modify Response Header
- 2 Create a rule that sets Content-Security-Policy to the desired value
- 3 Deploy the rule
Header name: Content-Security-Policy
Value: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'AWS CloudFront
- 1 Create a Response Headers Policy in CloudFront
- 2 Attach the policy to your distribution's behavior
Custom header:
Name: Content-Security-Policy
Value: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
Override origin: YesVercel
- 1 Add a headers entry to your vercel.json
- 2 Redeploy
json
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Content-Security-Policy", "value": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" }
]
}
]
}Netlify
- 1 Add a headers section to your netlify.toml or _headers file
- 2 Redeploy
toml
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"Nginx
- 1 Add the header directive to your server or location block
- 2 Test config with nginx -t, then reload
nginx
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" always;Apache
- 1 Make sure mod_headers is enabled
- 2 Add the Header directive to your .htaccess or VirtualHost
apacheconf
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"Caddy
- 1 Add a header directive to your Caddyfile
- 2 Reload Caddy
caddyfile
header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"Next.js
- 1 Add CSP via headers in next.config.js or middleware
- 2 Use nonces for inline scripts if needed
javascript
// next.config.js
module.exports = {
async headers() {
return [{
source: "/(.*)",
headers: [{
key: "Content-Security-Policy",
value: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';",
}],
}];
},
};Express
- 1 Use helmet's contentSecurityPolicy middleware
- 2 Start strict, then loosen as needed
javascript
const helmet = require("helmet");
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:"],
},
}));Django
- 1 Install django-csp
- 2 Add the middleware and configure directives in settings.py
python
# pip install django-csp
# settings.py
MIDDLEWARE = [
'csp.middleware.CSPMiddleware',
# ...
]
CSP_DEFAULT_SRC = ("'self'",)
CSP_SCRIPT_SRC = ("'self'",)
CSP_STYLE_SRC = ("'self'", "'unsafe-inline'")Laravel
- 1 Add a middleware that sets the header
- 2 Register it in your HTTP kernel
php
// app/Http/Middleware/SecurityHeaders.php
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('Content-Security-Policy', 'default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'');
return $response;
}Rails
- 1 Set the header in your ApplicationController or config
ruby
# config/application.rb
config.action_dispatch.default_headers.merge!(
'Content-Security-Policy' => 'default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline''
)Spring Boot
- 1 Configure the header in your SecurityFilterChain
java
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.headers(h -> h
.addHeaderWriter(new StaticHeadersWriter("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"))
);
return http.build();
}WordPress
- 1 Use a plugin like HTTP Headers or add manually to .htaccess
- 2 Start with Report-Only to avoid breaking your site
apacheconf
# .htaccess - start with report-only
Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
# Once verified, switch to enforcing:
# Header always set Content-Security-Policy "..."Nuxt
- 1 Add the header to your nuxt.config.ts routeRules
- 2 Rebuild and redeploy
typescript
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/**': {
headers: { 'Content-Security-Policy': 'default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'' },
},
},
});ASP.NET
- 1 Add middleware in your Program.cs or Startup.cs
csharp
app.Use(async (context, next) =>
{
context.Response.Headers.Append("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'");
await next();
});Does your app still have this?
Scan your domain