devkult_
tools29converters34
home/headers/content-security-policy

Content-Security-Policy

response headersecurity

Restricts where a page may load scripts, styles, images and frames from — the main defence against cross-site scripting.

A CSP is an allow-list for your page. If an attacker manages to inject a <script> tag, the browser refuses to run it unless the policy allows its source. Modern policies use nonces or hashes rather than host lists, so only the scripts your server deliberately marked can run.

Syntax

Content-Security-Policy: <directive> <source> <source>; <directive> …

Defined in W3C — Content Security Policy Level 3.

Values

default-srcfallback for the other fetch directives
script-srcwhere scripts may come from ('self', nonces, hashes, hosts)
style-srcwhere stylesheets and inline styles may come from
img-srcwhere images may come from
connect-srcwhere fetch(), XHR and WebSockets may connect
frame-ancestorswhich sites may embed this page in a frame
object-srcplugins; set to 'none'
base-urirestricts the <base> element
form-actionwhere forms may submit
report-to / report-uriwhere the browser reports violations

Examples

Content-Security-Policy: default-src 'self'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none'

a strict starting point for a site that serves everything itself

Content-Security-Policy: script-src 'nonce-r4nd0m' 'strict-dynamic'; object-src 'none'; base-uri 'none'

a nonce-based policy: only scripts carrying this response's nonce run

Good to know

  • Roll out with Content-Security-Policy-Report-Only first: violations are reported, nothing breaks.
  • Avoid 'unsafe-inline' for scripts — it undoes most of CSP's protection. Use nonces or hashes.
  • A nonce must be random and new on every response; a fixed nonce protects nothing.
  • frame-ancestors 'none' replaces X-Frame-Options: DENY in modern browsers.

Further reading: Content Security Policy guide · Security headers checklist · Security headers generator

How to set Content-Security-Policy

Express
res.set("Content-Security-Policy", "default-src 'self'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none'");
Next.js (next.config.js)
module.exports = {
  async headers() {
    return [
      {
        source: "/(.*)",
        headers: [{ key: "Content-Security-Policy", value: "default-src 'self'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none'" }],
      },
    ];
  },
};
nginx
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none'" always;
Apache (.htaccess)
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none'"

Check it

Fetch only the response headers and filter for Content-Security-Policy. In the browser, it's under Response Headers in DevTools → Network.

curl -sI https://example.com/ | grep -i '^content-security-policy:'

To compare response headers across many URLs at once, use the HTTP Status Checker.

Frequently asked questions

Why does my CSP break inline scripts and styles?

Inline code is blocked unless the policy allows it with a nonce, a hash, or 'unsafe-inline'. Move scripts into files, or add a per-response nonce to both the policy and the script tags.

Can I set CSP in a meta tag?

Yes, with <meta http-equiv="Content-Security-Policy">, but frame-ancestors, report-uri and sandbox don't work there. Prefer the header.

Related headers