Critical Security Header

Content-Security-Policy

Learn how Content Security Policy (CSP) protects your website from XSS attacks and other injection vulnerabilities.

SiteSecurityScore Team·15 min read·Updated Feb 20, 2026

Content Security Policy (CSP) is one of the most powerful security mechanisms available to web developers today. This comprehensive guide will walk you through everything you need to know about implementing CSP to protect your website from cross-site scripting (XSS) attacks and other code injection vulnerabilities.

What is Content Security Policy?#

Digital code representing content security policy protection

Content Security Policy (CSP) is one of the most powerful security mechanisms available to web developers. It is a HTTP response header that tells browsers which content sources are permitted to load on your page. CSP works by defining a whitelist of approved origins for scripts, stylesheets, images, fonts, and other resource types. Any resource not matching the policy is blocked by the browser, preventing Cross-Site Scripting (XSS), clickjacking, and other code injection attacks.

  • Prevents execution of unauthorized inline scripts and eval-based code
  • Restricts which domains can serve scripts, styles, images, and other resources
  • Blocks mixed content by enforcing HTTPS for all resource loads
  • Provides reporting capabilities to detect policy violations in production
Defense in Depth

CSP is not a replacement for proper input validation and output encoding. It serves as a strong second line of defense. Even if an XSS vulnerability exists in your code, a properly configured CSP can prevent the injected script from executing.

Why CSP Matters#

Cross-Site Scripting (XSS) consistently ranks among the most common web application vulnerabilities. Traditional defenses like input validation and output encoding are essential but not foolproof. A single missed encoding in a complex application can lead to a full compromise. CSP addresses this by enforcing security at the browser level, providing a safety net that catches attacks even when application-level defenses fail.

  • XSS is the most common web vulnerability according to OWASP Top 10
  • A single XSS vulnerability can lead to session hijacking, data theft, or account takeover
  • CSP reduces the impact of XSS by preventing unauthorized script execution
  • CSP reporting helps security teams identify and fix vulnerabilities proactively

Understanding CSP Directives#

CSP policies are composed of directives that control specific resource types. Each directive specifies which sources are allowed for that resource type. The default-src directive serves as a fallback for any resource type that does not have its own directive specified.

  • default-src sets the fallback policy for all resource types not explicitly defined
  • script-src controls JavaScript execution, the most critical directive for XSS prevention
  • style-src controls which stylesheets can be applied to the page
  • img-src, font-src, connect-src, media-src each control their respective resource types
  • frame-ancestors replaces X-Frame-Options for clickjacking protection
Configuration
# Anatomy of a CSP header Content-Security-Policy: default-src 'self'; # Fallback: only same-origin script-src 'self' 'nonce-abc123'; # Scripts: same-origin + nonce style-src 'self' 'unsafe-inline'; # Styles: allow inline CSS img-src 'self' data: https:; # Images: self, data URIs, HTTPS connect-src 'self' api.example.com; # XHR/Fetch: self + API frame-ancestors 'self'; # Who can frame this page

Implementation Strategy#

Deploying CSP requires a careful, phased approach. Starting with a report-only policy allows you to identify what your application loads without breaking anything. Once you have a clear picture of your resource loading patterns, you can create and enforce a production policy.

  • Start with Content-Security-Policy-Report-Only to monitor without blocking
  • Use a reporting endpoint to collect violation reports and identify necessary sources
  • Gradually tighten the policy by removing overly broad sources
  • Avoid 'unsafe-inline' and 'unsafe-eval' whenever possible as they weaken CSP significantly
  • Use nonces or hashes for inline scripts instead of 'unsafe-inline'
Common Pitfall

Deploying a strict CSP without testing can break your application. Third-party widgets, analytics scripts, and ad networks often require specific CSP directives. Always start in report-only mode and analyze the violations before enforcing.

Server Configuration Examples#

Here is how to configure CSP in common web servers and frameworks. Remember that CSP policies can be complex, so test thoroughly in report-only mode first.

Configuration
# Apache (.htaccess) Header always set Content-Security-Policy "\ default-src 'self'; \ script-src 'self'; \ style-src 'self' 'unsafe-inline'; \ img-src 'self' data:; \ font-src 'self'; \ connect-src 'self'" # Nginx add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'" always; # Node.js / Express (using helmet) const helmet = require('helmet'); app.use(helmet.contentSecurityPolicy({ directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], imgSrc: ["'self'", "data:"], } }));

CSP Reporting and Monitoring#

CSP includes built-in reporting capabilities that send violation reports to a URL you specify. This is invaluable for both initial deployment and ongoing security monitoring. Reports include details about what was blocked, which page it occurred on, and what the violating resource was.

  • Use report-uri or report-to directives to specify your reporting endpoint
  • Violation reports include the blocked URI, violated directive, and document URI
  • Monitor reports to detect attempted XSS attacks in production
  • Use reports to identify legitimate resources that need to be added to the policy
  • Third party services like report-uri.com can aggregate and analyze CSP reports
Configuration
# CSP with reporting Content-Security-Policy: default-src 'self'; report-uri /csp-report # Report-only mode for testing Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

Best Practices and Common Mistakes#

Effective CSP implementation requires understanding common pitfalls and following established best practices. Here are the key recommendations for a strong Content Security Policy.

  • Never use 'unsafe-inline' and 'unsafe-eval' together as this effectively disables CSP for scripts
  • Use nonce-based or hash-based policies instead of 'unsafe-inline' for inline scripts
  • Keep your policy as restrictive as possible while maintaining functionality
  • Use frame-ancestors in CSP instead of the deprecated X-Frame-Options header
  • Regularly review and update your policy as your application evolves
  • Test your CSP with tools like Google's CSP Evaluator before deployment
Avoid These Mistakes

Setting script-src to 'unsafe-inline' 'unsafe-eval' provides almost no XSS protection. Using wildcard sources like *.googleapis.com can be exploited through JSONP endpoints. Always be as specific as possible with your allowed sources.

Implementation Examples#

Basic CSP Policy

Content-Security-Policy: default-src 'self'

This basic policy only allows resources from the same origin as your website. It's a good starting point that provides significant security improvements with minimal risk of breaking functionality.

Explanation: The 'self' keyword refers to the same scheme, host, and port as the document. This means if your site is https://example.com, only resources from https://example.com will be allowed.

Intermediate CSP Policy

Content-Security-Policy: default-src 'self'; script-src 'self' https://apis.google.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:

This policy provides more granular control by specifying different rules for different resource types. It allows Google APIs for scripts, inline styles, and images from HTTPS sources.

Explanation: This configuration is common for websites that use external APIs or CDNs. The 'unsafe-inline' for styles is often necessary for CSS frameworks, though it should be avoided when possible.

Strict CSP Policy

Content-Security-Policy: default-src 'none'; script-src 'self' 'nonce-{random}'; style-src 'self' 'nonce-{random}'; img-src 'self' data:; connect-src 'self'

A very restrictive policy that uses nonces for inline scripts and styles. This provides maximum security but requires more careful implementation.

Explanation: Using nonces (cryptographically secure random values) allows you to permit specific inline scripts while blocking all others. This is the most secure approach but requires server-side implementation.

Key Directives#

default-src

Serves as a fallback for other resource types when they don't have policies of their own

default-src 'self'

script-src

Controls which JavaScript sources are allowed to execute

script-src 'self' https://trusted-cdn.com

style-src

Controls which CSS stylesheets can be applied

style-src 'self' 'unsafe-inline'

img-src

Controls which image sources can be loaded

img-src 'self' data: https:

connect-src

Controls which servers can be contacted via AJAX, WebSocket, and EventSource

connect-src 'self' https://api.example.com

font-src

Controls which font sources can be loaded

font-src 'self' https://fonts.googleapis.com

object-src

Controls which plugin sources can be loaded (Flash, etc.)

object-src 'none'

media-src

Controls which audio and video sources can be loaded

media-src 'self' https://videos.example.com

References#

Was this helpful?
Share

Test Your Content-Security-Policy Configuration

Scan your site to check if Content-Security-Policy is properly configured.