What is Content-Security-Policy?
Every time a browser loads your website, it pulls in dozens of resources — JavaScript files, CSS stylesheets, images, fonts, iframes, and many other resources needed to display the page correctly. By default, the browser doesn't care where these resources come from — its job is simply to load them. This means that an attacker who finds a way to inject code into your page can load malicious scripts onto it — and the browser will execute them.
The Content Security Policy (CSP) header changes this. It is an HTTP response
header that you add to your server configuration. This header contains a set
of rules (called directives) that tell the browser exactly which sources are
trusted for each type of resource. For example, you can say: "Only load
JavaScript from my own domain and don't use any third-party resources," or
"Only load images from my domain and from cdn.example.com.
Block everything else."
If the browser encounters a resource that violates your policy — for example, a script trying to load from an unknown domain — it immediately blocks it and logs the violation in the developer console. This means that even if an attacker finds an XSS vulnerability in your application and somehow injects a connection to their third-party script, CSP will prevent the malicious code from executing.
Recommended Value
To protect your website from these threats, add the Content-Security-Policy header to your web server configuration. Choose the example below depending on which server you use.
Nginx
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" always;
Apache
Header Common Mistakes
- Using unsafe-inline and unsafe-eval in script-src — these values effectively disable CSP protection. Inline scripts and eval() are the primary attack vectors for XSS. Use nonce or hash instead.
- Setting default-src * or broad wildcards — allowing resources from any domain provides no real protection.
- Missing object-src — the <object> and <embed> elements
can be used to bypass script restrictions. Always set
object-src 'none'. - Missing frame-ancestors — without this directive, your site can be embedded in an iframe on an attacker's page, enabling clickjacking attacks.
- Deploying without Report-Only — enforcing CSP immediately
is risky. Start with
Content-Security-Policy-Report-Onlyto detect issues without breaking legitimate resources.
By implementing these settings and recommendations, you will significantly improve your CSP score and protect your website from malicious exploits.