Content-Security-Policy Generator

Build a strong CSP header with our visual editor. Start with a preset for your platform, customize per directive, and copy-paste the result into Nginx, Apache, Express, Next.js, Vercel, or Django. Free, no signup required.

CSP is the single most effective HTTP header against Cross-Site Scripting (XSS) attacks. It tells the browser exactly which sources can load scripts, styles, and other resources. Anything not in the policy gets blocked.

Quick presets

Start with a preset tuned for your stack, then customize. Each preset balances security with compatibility for the platform.

Directives

default-src
Fallback for every resource type not explicitly listed. If a directive is missing, the browser checks default-src.
script-src
Controls which origins can serve JavaScript. The most critical directive for stopping XSS.
style-src
Controls which origins can serve CSS. 'unsafe-inline' is common but weakens protection.
img-src
Controls where images can load from. Include data: if you use Base64-encoded images.
font-src
Controls where web fonts load from. Add Google Fonts or your CDN origin here.
connect-src
Controls endpoints for fetch(), XMLHttpRequest, WebSocket, and EventSource.
frame-src
Controls which origins can be loaded in <iframe>. Keep 'none' unless you embed third-party widgets.
object-src
Controls <object>, <embed>, and <applet>. Always set to 'none'. Plugins are a legacy attack vector.

Generated CSP header

default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; media-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'

Copy-paste examples

Nginx
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; media-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always;
Apache (.htaccess)
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; media-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'"
Express / Node.js
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    'default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; media-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none''
  );
  next();
});
Next.js (next.config.js)
const securityHeaders = [
  {
    key: 'Content-Security-Policy',
    value: `default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; media-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'`
  }
];

module.exports = {
  async headers() {
    return [{ source: '/(.*)', headers: securityHeaders }];
  }
};
Vercel (vercel.json)
{
  "headers": [{
    "source": "/(.*)",
    "headers": [{
      "key": "Content-Security-Policy",
      "value": "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; media-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'"
    }]
  }]
}
Django (middleware)
# settings.py. Use django-csp:
# pip install django-csp
CSP_DEFAULT_SRC = ("'self'",)
CSP_SCRIPT_SRC = ("'self'",)
CSP_OBJECT_SRC = ("'none'",)
Pro tip: Test before enforcing

Replace Content-Security-Policy with Content-Security-Policy-Report-Only to log violations without blocking anything. Monitor your browser console or a reporting endpoint to find resources that need to be added before switching to enforcement mode.

What is Content-Security-Policy?

Content-Security-Policy (CSP) is an HTTP response header that creates an allowlist of trusted sources for your web page. When a browser loads your page and sees the CSP header, it enforces the policy: any script, stylesheet, image, font, or other resource that doesn't match an allowed source is blocked from loading.

CSP was designed to stop Cross-Site Scripting (XSS). Classified as OWASP Top 10 A03:2021, the most common web vulnerability. XSS attacks inject malicious JavaScript into your page. Through form fields, URL parameters, or stored data. Without CSP, the browser executes the injected script because it can't distinguish it from your legitimate code. With CSP, the browser checks the script's origin against your policy and blocks it if it's not on the allowlist.

CSP also protects against clickjacking (via frame-ancestors. See W3C CSP Level 3 spec), data exfiltration (via connect-src), form hijacking (via form-action), and plugin-based attacks (via object-src). A single header blocks entire categories of attacks that would otherwise require application-level fixes.

How CSP works. Step by step

1
Server sends the header
Your web server includes the Content-Security-Policy header in every HTTP response. The header contains a list of directives, each specifying which sources are allowed for a resource type.
2
Browser parses the policy
When the browser receives the response, it reads the CSP header and builds an internal allowlist for each resource type (scripts, styles, images, etc.).
3
Resources are checked
As the page loads, every resource request is checked against the policy. A script from cdn.example.com is allowed only if cdn.example.com is listed in script-src (or default-src as fallback).
4
Violations are blocked
Any resource that doesn't match the policy is blocked. The browser logs a violation in the console. If you've configured report-uri or report-to, the violation is also sent to your reporting endpoint.

CSP directive reference

Each directive controls a specific resource type. If a directive is not set, the browser falls back to default-src. Setting default-src 'self' as your baseline and overriding per directive is the recommended approach.

DirectiveControlsRecommended
default-srcFallback for all resource types'self'
script-srcJavaScript execution'self' (use nonces for inline)
style-srcCSS loading'self' (inline OK if needed)
img-srcImage loading'self' data:
font-srcWeb font loading'self'
connect-srcfetch, XHR, WebSocket'self' + your API
frame-srciframe embedding'none'
object-srcPlugins (object, embed)'none' (always)
base-uribase tag URL'self'
form-actionForm submission targets'self'
frame-ancestorsWho can embed your page'none'
media-srcAudio and video'self'

CSP best practices

Start strict, loosen as needed
Begin with default-src 'self' and object-src 'none'. Add exceptions only when something breaks. It's easier to allow a specific source than to realize you forgot to block one.
Never use 'unsafe-inline' for scripts
Use nonces ('nonce-<random>') or hashes ('sha256-<hash>') to allow specific inline scripts without opening the door to all inline code. Most modern frameworks support nonce-based CSP.
Always set object-src 'none'
Flash, Java applets, and other plugins are obsolete attack vectors. Setting object-src 'none' costs nothing and blocks an entire class of exploits.
Use Report-Only mode first
Deploy with Content-Security-Policy-Report-Only to collect violations without breaking anything. Review the reports, add missing sources, and switch to enforcing mode when clean.
Add frame-ancestors to prevent clickjacking
Set frame-ancestors 'none' (or 'self' if you need self-framing) to prevent your site from being embedded in malicious iframes. This replaces X-Frame-Options with more granular control.
Avoid wildcards and https:
Don't use * or https: as source values. They allow any origin and defeat the purpose of CSP. Allowlist specific domains: https://cdn.example.com is far safer than https:.
Keep your policy maintained
CSP is not set-and-forget. When you add a new third-party script, CDN, or analytics tool, update your policy. Use our header checker to verify your policy stays correct over time.

Common CSP mistakes

MistakeWhy it's badFix
script-src with unsafe keywordsAllows all inline scripts. CSP is effectively disabled for XSSUse nonces or hashes instead
default-src *Allows loading from any origin. No protection at allUse 'self' and add specific domains
Missing object-srcFalls back to default-src, may allow plugin executionAlways set object-src 'none'
Using http: sourcesAllows mixed content, enables MITM attacksOnly allow https: sources
Too many wildcards*.example.com allows any subdomain including attacker-controlled onesList specific subdomains
Forgetting connect-srcFalls back to default-src, may block your API callsAdd your API domain to connect-src

CSP implementation by framework

Next.js (App Router)

Next.js supports CSP via middleware for dynamic nonce generation, or via next.config.js for static policies. Use middleware if you need nonces for inline scripts.

// middleware.ts
import { NextResponse } from 'next/server';

export function middleware(request) {
  const nonce = Buffer.from(
    crypto.randomUUID()
  ).toString('base64');

  const csp = [
    "default-src 'self'",
    `script-src 'self' 'nonce-${nonce}'`,
    "style-src 'self' 'unsafe-inline'",
    "img-src 'self' data:",
    "object-src 'none'",
    "base-uri 'self'",
    "frame-ancestors 'none'"
  ].join('; ');

  const response = NextResponse.next();
  response.headers.set(
    'Content-Security-Policy', csp
  );
  response.headers.set('x-nonce', nonce);
  return response;
}

Laravel

Add CSP via middleware or use the spatie/laravel-csp package for a structured approach.

// app/Http/Middleware/CspHeader.php
public function handle($request, Closure $next)
{
    $response = $next($request);
    $response->headers->set(
        'Content-Security-Policy',
        "default-src 'self'; "
        . "script-src 'self'; "
        . "object-src 'none'; "
        . "frame-ancestors 'none'"
    );
    return $response;
}

Django

Use django-csp for declarative CSP or set headers in custom middleware.

# pip install django-csp
# settings.py
MIDDLEWARE = [
    'csp.middleware.CSPMiddleware',
    # ...
]
CSP_DEFAULT_SRC = ("'self'",)
CSP_SCRIPT_SRC = ("'self'",)
CSP_STYLE_SRC = ("'self'", "'unsafe-inline'")
CSP_IMG_SRC = ("'self'", "data:")
CSP_OBJECT_SRC = ("'none'",)
CSP_FRAME_ANCESTORS = ("'none'",)
CSP_BASE_URI = ("'self'",)

Ruby on Rails

Rails has built-in CSP support via the content_security_policy initializer.

# config/initializers/content_security_policy.rb
Rails.application.configure do
  config.content_security_policy do |policy|
    policy.default_src :self
    policy.script_src  :self
    policy.style_src   :self, :unsafe_inline
    policy.img_src     :self, :data
    policy.object_src  :none
    policy.frame_ancestors :none
    policy.base_uri    :self
  end
end

Cloudflare Workers

Add CSP at the edge for any origin behind Cloudflare.

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const response = await fetch(request);
  const newResponse = new Response(
    response.body, response
  );
  newResponse.headers.set(
    'Content-Security-Policy',
    "default-src 'self'; "
    + "script-src 'self'; "
    + "object-src 'none'"
  );
  return newResponse;
}

Frequently asked questions

What is a Content-Security-Policy header?+

Content-Security-Policy (CSP) is an HTTP response header that tells the browser which sources are allowed to load resources like scripts, styles, images, and fonts. It acts as an allowlist. Anything not explicitly permitted is blocked. CSP is the single most effective defense against Cross-Site Scripting (XSS) attacks.

How does CSP prevent XSS attacks?+

XSS attacks work by injecting malicious scripts into your page. CSP blocks these scripts because the attacker's origin is not in your allowlist. Even if an attacker manages to inject a script tag, the browser refuses to execute it because the source violates the policy. This makes CSP a critical layer of defense beyond input sanitization.

What does 'unsafe-inline' mean and should I use it?+

'unsafe-inline' allows execution of inline script tags and inline event handlers (onclick, onerror, etc.). This significantly weakens CSP because attackers who can inject HTML can also inject inline scripts. Avoid it for script-src whenever possible. Use nonces or hashes instead. For style-src, 'unsafe-inline' is more common because many CSS frameworks rely on inline styles.

What is the difference between CSP and X-Frame-Options?+

X-Frame-Options only controls whether your page can be framed (embedded in an iframe). CSP's frame-ancestors directive does the same thing but with more flexibility. You can allow specific origins instead of just DENY or SAMEORIGIN. CSP also covers scripts, styles, images, fonts, connections, and many other resource types. Use both for maximum browser compatibility.

How do I test CSP without breaking my site?+

Use Content-Security-Policy-Report-Only instead of Content-Security-Policy. This tells the browser to report violations without actually blocking anything. Add a report-uri or report-to directive to collect violation reports. Monitor the reports, fix any legitimate resources that get flagged, then switch to enforcing mode.

Why does my site break after adding CSP?+

CSP blocks any resource not explicitly allowed. Common causes: inline scripts or styles (need 'unsafe-inline' or nonces), third-party analytics scripts (add their domain to script-src), Google Fonts (add fonts.googleapis.com to style-src and fonts.gstatic.com to font-src), CDN-hosted libraries (add the CDN domain to script-src). Start with Report-Only mode to identify what needs to be allowed.

What is a CSP nonce and how do I use it?+

A nonce is a random, single-use token generated on each page load. You add it to your CSP header (script-src 'nonce-abc123') and to each inline script tag. The browser only executes scripts with a matching nonce. This is safer than 'unsafe-inline' because an attacker cannot guess the nonce. Your server must generate a new nonce for every response.

Do I need CSP if I already sanitize user input?+

Yes. Input sanitization is important but not foolproof. Bypasses are discovered regularly. CSP is a defense-in-depth layer. Even if sanitization fails and an attacker injects a script, CSP blocks it from executing. Think of CSP as your seatbelt: you still drive carefully, but the seatbelt saves you when something goes wrong.

Which CSP directives should I always set?+

At minimum: default-src 'self' (baseline), script-src 'self' (block injected scripts), object-src 'none' (block plugins), base-uri 'self' (prevent base tag hijacking), and frame-ancestors 'none' (prevent clickjacking). These five directives block the most common attack vectors with minimal compatibility impact.

How do I add CSP to my Next.js or Vercel project?+

In Next.js, add a headers() function in next.config.js or use middleware. For Vercel, add a headers array in vercel.json. You can also set CSP in a custom middleware.ts file for dynamic nonce generation. Our generator provides copy-paste code for both approaches.

Related resources

Test your CSP on a live site

Use our header checker to verify your CSP is deployed correctly, or run a full scan covering 150+ security checks.

Run Full Security Scan