Skip to main content

Content Security Policy (CSP)

Updated: October 29, 2026
By Willya Randika

CSP is an HTTP header that decides which sources may load scripts, styles, images, fonts, and connections. It does not close every XSS hole, but it limits what injected code can do. If an attacker adds a script tag, the browser refuses to run it from a domain you did not allow.

The directives you will use most

default-src is the fallback for every resource. script-src controls JavaScript, including inline scripts and workers. style-src controls CSS. img-src controls images. connect-src controls fetch, XHR, WebSocket, and beacons. frame-ancestors stops other sites from embedding the page, while form-action limits where forms may submit.

'self' means the same origin. A nonce or hash allows a specific script without opening every inline script. Avoid 'unsafe-inline' in script-src; it makes XSS protection much weaker.

An example header from the app

Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://cdn.example.com; connect-src 'self' https://api.example.com; frame-ancestors 'self'; base-uri 'self'; form-action 'self'

The nonce in the header must match the nonce rendered by the app in the script tag. The app generates a random nonce per request, uses that value in the HTML, and sends the same header. Do not generate a separate nonce in Nginx because it will not match the HTML.

Start with report-only

Do not enforce the full policy on day one. Use Content-Security-Policy-Report-Only first. The browser reports violations without blocking resources. Open DevTools Console, look for “Refused to load” messages, then fix chat widgets, analytics, fonts, and payment iframes that are not allowed yet.

Once the violation list is clean, enforce one directive at a time. Test login, checkout, and forms before tightening the policy. Send reports to your own endpoint with report-to or report-uri, and cap the log size so it does not flood the server.

What makes CSP fail

A policy copied from another site often blocks important assets. Allowing unsafe-inline to avoid work weakens the main protection. Forgetting frame-ancestors leaves the page embeddable. And CSP does not replace input validation or output escaping.

CSP complements HSTS, which secures transport, and a WAF, which filters requests at the server. They work at different layers.

If the application loads resources from another origin, configure CORS as well.

FAQ

Does CSP slow down a site?

The overhead is usually small. It grows when there are many violation reports or the policy is applied by a slow app layer. Measure with DevTools before drawing conclusions.

Can CSP replace a WAF?

No. CSP is a browser control. A WAF inspects requests at the server. They handle different threats.

Why are Google Fonts blocked after enabling CSP?

Add the font domain to font-src and style-src, or self-host the fonts. Do not reach for * just to silence the error.

Disclaimer: Hosting Wiki articles are prepared for educational and reference purposes. Hosting technology keeps evolving, so some technical details may change over time.