LinkedIn Tag

What is a Content Security Policy (CSP)?

Content Security Policy (CSP) is a browser security feature that was implemented to mitigate against certain types of browser-based attacks, like cross-site scripting.

Simon Wijckmans
Simon Wijckmans
Founder & CEO

Content Security Policy

A Content Security Policy (CSP) is a browser security standard defined by the World Wide Web Consortium (W3C). It helps developers protect websites from client-side attacks such as cross-site scripting (XSS) and data injection. By specifying trusted sources for scripts, styles, and media, a CSP acts as a whitelist that browsers enforce automatically as part of the browser’s client-side security model.

Summary (TL;DR)

  • CSP defines which sources a browser can trust.
  • It helps block injected or unauthorized scripts.
  • It reduces XSS and data exfiltration risks.
  • Best used together with input validation and HTTPS.
  • Requires ongoing maintenance and testing.

Understanding Content Security Policy (CSP)

Content Security Policy (CSP) is a browser security feature that was implemented to mitigate certain types of browser-based attacks, like cross-site scripting. The CSP was standardized by the World Wide Web Consortium (W3C) in the CSP Level 3 specification, it allows a website to send a set of rules (via HTTP response headers or <meta> tags inside the HTML <head>) that instructs the browser which content sources are allowed.

These rules, called directives, specify approved origins for scripts, images, styles, iframes, and more. The primary purpose of using CSP is to have full control of where scripts are loaded from, along with controlling which scripts a page is permitted to execute, thus attempting to prevent injected or unauthorized scripts from running.

For example, a CSP directive might state that scripts should only load from the site’s own domain (done by using ‘self’), or from specific trusted domains. The browser will then block any script file or inline script that’s not from an allowed source, providing a crucial defense against XSS attacks where an attacker tries to inject malicious <script> tags or code into a site. These days, most browsers also support CSP ‘Report-only’ mode. This allows developers to test a policy safely. When enabled, policy violations are logged to a reporting endpoint instead of being blocked right away. When CSP is being deployed for the first time, this is a best practice.

How Content Security Policy (CSP) Works

A Content Security Policy is delivered to a browser via the HTTP response header named `Content-Security-Policy`, or via a meta tag in the HTML <head>. The policy consists of directives separated by semicolons, and each directive controls a specific resource type.

  • ‘script-src’ self: allows scripts only from the same origin. Any <script> from another domain (or inline script code) is blocked by the browser.
  • ‘connect-src’ self https://api.domain.com : allows AJAX/XHR/fetch calls only to the same site, or to the trusted domain api.domain.com. This prevents malicious code from exfiltrating data to unknown servers from the site.
  • img-src 'self' data: can be used to only load images from the same site and block external images - which can be used to prevent data leaks via image requests.

CSP Nonces and CSP Hashes

CSP also supports advanced mechanisms such as nonces ('nonce-abc123') and hashes ('sha256-xyz...'). These allow inline scripts to execute safely by cryptographically proving their integrity. Instead of banning all inline code, developers can selectively authorize specific scripts, improving flexibility without sacrificing security.

There are multitudes of other directives that can be used for other data types like media, fonts, iframes, etc. but the core idea of using a Content Security Policy is to whitelist trusted sources. When the browser loads a page and asks what content to load, it will first refer to the CSP and enforce these rules on every load. Any script or resource that loads this policy won’t be loaded. For a detailed implementation guide, check the OWASP CSP Cheat Sheet.

Common CSP Directives And Their Purpose

Directive Purpose Typical Use Case
default-src Sets a baseline policy for all resources when no other rule applies. Start strict: default-src 'none';
script-src Controls which JavaScript sources are allowed. Whitelist 'self', CDNs, or use nonce/hash-based scripts.
style-src Limits where CSS can load from. Use 'self'; avoid 'unsafe-inline' when possible.
img-src Defines trusted image sources. Prevent data leaks via external image calls.
connect-src Restricts AJAX, fetch, and WebSocket destinations. Block data exfiltration to unknown domains.
frame-ancestors Specifies which sites may embed your pages in iframes. Prevent clickjacking: frame-ancestors 'none';
report-uri / report-to Defines where CSP violation reports are sent. Log and analyze CSP breaches for policy tuning.

How a CSP can Protect a Website

Mitigation of XSS attacks: In a cross-site scripting attack, or XSS attack, an attacker generally finds a way to inject and execute malicious JavaScript code into your page (like on an unsanitized input). By default, a CSP will block any inline scripts from executing on the page, unless a policy directive explicitly allows it. This means an attacker that injects something like `<script>evilCode()</script>` into a page, it won’t execute (unless ‘unsafe-inline’ is disallowed in the CSP!)

Blocking unauthorized third-party scripts: Many sites have third-party scripts for things like analytics, user tracking, and advertisements. With a CSP, site owners can limit which external sites can actually deliver scripts. For example, if you’re only looking to serve content from `analytics.example.com` and not anything else from example.com, your site’s CSP script-src directive can explicitly allow only that.

Preventing data exfiltration: As previously mentioned, a CSP can restrict actions on a page that can be used to stop malicious JavaScript code from sending data back to an attacker controlled domain. Using the `connect-src` directive blocks network requests to unauthorised servers, and can be used in combination with the `form-action` directive to ensure the data is only being sent to your domain. 

Enforce safe browsing practices: A CSP has directives to enforce safe behaviors that improve your site’s security in general. One example of this is `upgrade-insecure-requests`, which forces the browser to load all resources over HTTPS, preventing mixed and insecure content issues. Another directive is `frame-ancestors`, which can prevent clickjacking attacks by disallowing your page to be embedded in an attacker-controlled frame. 

How CSP Prevents Browser-Based Attacks

1. Mitigation of XSS attacks: 

In a cross-site scripting attack, or XSS attack, an attacker generally finds a way to inject and execute malicious JavaScript code into your page (like on an unsanitized input). By default, a CSP will block any inline scripts from executing on the page, unless a policy directive explicitly allows it. This means an attacker that injects something like `<script>evilCode()</script>` into a page, it won’t execute (unless ‘unsafe-inline’ is disallowed in the CSP!) 

2. Blocking unauthorized third-party scripts: 

Many sites have third-party scripts for things like analytics, user tracking, and advertisements. With a CSP, site owners can limit which external sites can actually deliver scripts. For example, if you’re only looking to serve content from `analytics.example.com` and not anything else from example.com, your site’s CSP script-src directive can explicitly allow only that.

3. Preventing data exfiltration: 

As previously mentioned, a CSP can restrict actions on a page that can be used to stop malicious JavaScript code from sending data back to an attacker controlled domain. Using the `connect-src` directive blocks network requests to unauthorised servers, and can be used in combination with the `form-action` directive to ensure the data is only being sent to your domain. 

4. Enforce safe browsing practices:

A CSP has directives to enforce safe behaviors that improve your site’s security in general.

  • One example of this is `upgrade-insecure-requests`, which forces the browser to load all resources over HTTPS, preventing mixed and insecure content issues.
  • Another directive is `frame-ancestors`, which can prevent clickjacking attacks by disallowing your page to be embedded in an attacker-controlled frame. 

Combined, these policies result in a robust client-side baseline for modern web apps.

Security Limitations of CSP

Using a Content Security Policy provides strong protection but it isn’t an end-all-be-all solution for your site, as highlighted in our post “Why Content Security Policy Doesn’t Work”.

Policies can drift over time, and allowlists don’t inspect code behavior. Every major browser implements CSP in its own, slightly different way. Chrome, Firefox, Safari, and Edge all support CSP Level 3; reporting behavior and violation formats may vary. To validate and maintain your policy, regularly test it with browser developer tools and automated scanners such as Mozilla Observatory or SecurityHeaders.io. 

Pairing a CSP with an active client-side proxy like cside to add real-time inspection and blocking to third-party scripts on your site gives you a great layer of defense, with peace of mind for your customers. From a governance perspective, documenting CSP updates and monitoring violation reports improves auditability and long-term compliance with frameworks such as ISO 27001 and OWASP ASVS.

Does CSP Work for PCI DSS 6.4.3 Compliance?

Under PCI DSS 4.0.1 Requirement 6.4.3, merchants must prove every client-side script is authorized and prove script integrity. CSP and SRI get you part of the way there. CSP limits which domains can load scripts, and SRI checks that a file’s code hasn’t changed. But together they’re a static solution to a dynamic problem. Dynamic scripts update and hashes break. Manual maintenance of CSP lists is nearly impossible.

Most modern sites use dynamic third-party scripts so these controls degrade fast. This approach will typically fall short of the required evidence needed for PCI 6.4.3.

An Example of a Misconfigured CSP

The day check-out stopped working: How a Strict CSP Broke Production

It all began with just an ordinary new deployment. Nothing special, just a new Content Security Policy to make an ecommerce shop more secure and block attackers from sneaking in bad code.

The clean default-src 'none’ was set without testing. And so, the moment the CSP was activated, the website blocked services it actually needed. Analytics stopped working and worst of all, the payment system was blocked. Customers couldn’t complete their orders and the check-out system broke. Developers went to work and switched the header to Content-Security-Policy-Report-Only and collected violation logs. From there, they built an allowlist (script-src 'self' https://pay.examplecase.com) with all the services the webshop needed to run properly.

Refining the CSP enabled deployment with zero breakage. Unfortunately, this oversight is a common mishap when teams manage CSP internally. Forgetting to whitelist a new marketing script, technical misconfigurations, or issues with dynamic scripts that break hashing protocols make CSP a nightmare to manage at scale.

Why do I need a CSP if I validate inputs & sanitize data?

Input validation helps reduce risk but doesn't necessarily stop it. A CSP provides an additional layer of defense by restricting what resources can and can’t be loaded - meaning that even if a piece of malicious code slips through, the browser can still block it from running. 

Does a CSP completely stop XSS attacks?

Absolutely not. CSP can reduce the attack surface for cross-site scripting, but it’s not the silver bullet. Misconfigurations of the CSP, overly broad allowlists, or the use of `unsafe-inline` can still leave your site vulnerable.

Will a CSP break my site?

Yes, if not implemented properly. A CSP can block legitimate resources such as third-party libraries your website relies on. That’s also why it’s important to test and to fine-tune your rules before enforcing them. 

How hard is it to maintain a CSP?

Maintenance can be challenging, especially if your site relies heavily on third-party scripts. Policies need regular updates as websites evolve - and a service like cside can help ease some of the ongoing maintenance.

Will a CSP affect my site’s performance?

Generally, no. The browser will simply check the resources against the CSP before blocking them. The performance implications are negligible compared to the security benefits you would gain. The concern is configuration time, not runtime.

Preguntas Frecuentes

Preguntas Frecuentes

Input validation helps reduce risk but doesn't necessarily stop it. A CSP provides an additional layer of defense by restricting what resources can and can’t be loaded - meaning that even if a piece of malicious code slips through, the browser can still block it from running. 

Absolutely not. CSP can reduce the attack surface for cross-site scripting, but it’s not the silver bullet. Misconfigurations of the CSP, overly broad allowlists, or the use of `unsafe-inline` can still leave your site vulnerable.

Yes, if not implemented properly. A CSP can block legitimate resources such as third-party libraries your website relies on. That’s also why it’s important to test and to fine-tune your rules before enforcing them. 

Maintenance can be challenging, especially if your site relies heavily on third-party scripts. Policies need regular updates as websites evolve - and a service like cside can help ease some of the ongoing maintenance.

Generally, no. The browser will simply check the resources against the CSP before blocking them. The performance implications are negligible compared to the security benefits you would gain. The concern is configuration time, not runtime.

Artículos Relacionados