Content-Security-Policy

Provides Content-Security-Policy HTTP headers to protect against XSS and other code injection attacks by controlling which resources can be loaded by the browser.

csp
18,854 sites
93
drupal.org

Install

Drupal 11, 10 v2.2.2
composer require 'drupal/csp:^2.2'

Overview

The Content-Security-Policy (CSP) module enables Drupal sites to send Content-Security-Policy HTTP headers, a powerful security mechanism that helps prevent cross-site scripting (XSS), clickjacking, and other code injection attacks. CSP allows site administrators to specify which origins are trusted sources for scripts, stylesheets, images, fonts, and other resources.

The module provides a comprehensive administrative interface for configuring both Report-Only and Enforced policies, with support for all standard CSP directives. It automatically detects external resources defined in Drupal libraries and adds them to the policy, reducing manual configuration. The module also includes support for nonces and hashes to allow specific inline scripts and styles while blocking others.

For developers, the module provides services and events to programmatically modify the CSP policy, as well as a plugin system for implementing custom reporting handlers. Themes can use a dedicated alter hook to modify the policy as needed.

Features

  • Dual policy support: Configure both Report-Only and Enforced Content-Security-Policy headers independently
  • Comprehensive directive support: Configure all CSP3 directives including default-src, script-src, style-src, img-src, font-src, connect-src, frame-src, frame-ancestors, form-action, base-uri, object-src, worker-src, manifest-src, media-src, prefetch-src, sandbox, webrtc, trusted-types, and more
  • Automatic library detection: Scans all enabled modules and themes to automatically include external script and stylesheet sources from library definitions
  • Nonce support: Per-request cryptographic nonce generation for allowing specific inline scripts and styles while maintaining security
  • Hash support: Calculate and include SHA-256, SHA-384, or SHA-512 hashes for whitelisting specific inline code
  • Flexible source configuration: Set base policy (self, none, any) and add additional allowed sources per directive
  • Keyword flags support: Enable flags like 'unsafe-inline', 'unsafe-eval', 'unsafe-hashes', 'report-sample', 'wasm-unsafe-eval', and 'inline-speculation-rules' for applicable directives
  • Pluggable reporting system: Built-in support for custom URI endpoints and Report-URI.com integration, with plugin architecture for custom reporting handlers
  • CKEditor5 integration: Automatically adds required exceptions when CKEditor5 is present on a page
  • Policy optimization: Automatically reduces redundant sources and removes directives that match fallback values
  • Firefox bug workaround: Includes workaround for Firefox bug with nonces/hashes in default-src
  • Event-driven architecture: CspEvents::POLICY_ALTER event allows modules to modify the policy before it's sent
  • Theme hook support: hook_csp_policy_alter allows themes to customize the policy
  • Render element integration: Attach CSP sources, nonces, and hashes directly to render elements

Use Cases

Basic XSS Protection

Enable both Report-Only and Enforce policies with 'self' as the base for script-src and style-src. This prevents loading of external scripts and styles that could be injected by attackers. Use the Report-Only policy first to identify any legitimate external resources that need to be allowed.

Preventing Clickjacking

Configure the frame-ancestors directive with 'self' or 'none' to prevent your pages from being embedded in frames on other sites. This protects against clickjacking attacks where attackers overlay transparent iframes over legitimate content.

Allowing CDN Resources

Add CDN hostnames (e.g., 'https://cdn.example.com') to the appropriate directives (script-src, style-src, font-src, img-src) to allow resources from trusted CDNs while blocking unknown sources. The module automatically detects many CDN sources from Drupal library definitions.

Using Nonces for Inline Scripts

For modules that need to add inline scripts, use the csp.policy_helper service to add nonces. Attach 'csp_nonce' to render elements with a fallback value. The nonce is automatically added to script-src-elem and the header, allowing specific inline scripts while blocking others.

Mixed Content Upgrade

Enable 'upgrade-insecure-requests' in the Enforce policy to automatically upgrade HTTP requests to HTTPS, helping with HTTPS migration without breaking resources referenced with HTTP URLs.

Third-Party Widget Integration

When embedding third-party widgets (Google Maps, social media embeds, etc.), add the required domains to frame-src, script-src, and style-src directives. Start with Report-Only mode to discover all required sources, then move to Enforce mode.

Implementing Trusted Types

Enable trusted-types and require-trusted-types-for directives to prevent DOM-based XSS by requiring the use of Trusted Types API for dangerous DOM manipulation sinks. This is an advanced feature for applications with complex JavaScript.

Tips

  • Always start with Report-Only mode to discover required sources before enforcing the policy
  • Use the Report-URI.com Wizard feature during development to easily build your policy
  • The 'report-sample' flag helps identify which inline scripts or styles are causing violations
  • External sources defined in *.libraries.yml files are automatically detected - check if libraries are properly defined before manually adding sources
  • Use browser developer tools (Console and Network tabs) to identify CSP violations
  • The frame-ancestors directive replaces the older X-Frame-Options header for clickjacking protection
  • Consider enabling 'upgrade-insecure-requests' when migrating to HTTPS to avoid mixed content issues
  • When using nonces, always provide a fallback value for browsers that may not support nonces
  • Directives marked with 'auto' in the admin interface have sources automatically detected from libraries

Technical Details

Admin Pages 1
Content Security Policy /admin/config/system/csp

Configure Content-Security-Policy headers for your site with support for both Report-Only and Enforced policies. The page uses vertical tabs to separate policy configuration.

Permissions 1
Administer Content Security Policy

Allows users to configure Content-Security-Policy headers. This permission is restricted and should only be granted to trusted administrators.

Hooks 1
hook_csp_policy_alter

Allows themes to alter the CSP policy for the current response. This hook is only invoked for themes; modules should use the CspEvents::POLICY_ALTER event instead.

Troubleshooting 6
CSP violations blocking legitimate functionality

Start with Report-Only mode enabled and Enforce disabled. Monitor browser console and reporting endpoint for violations. Add necessary sources to the appropriate directives. Only enable Enforce mode after all legitimate sources are allowed.

CKEditor5 not working properly

The module automatically adds 'unsafe-inline' for CKEditor5 when detected. Ensure the module is detecting CKEditor5 correctly. If issues persist, manually add 'unsafe-inline' to style-src directives.

External library scripts being blocked

Check if the library is defined in a *.libraries.yml file with the external URL. The module auto-detects these. If not auto-detected, manually add the host to script-src-elem and script-src directives.

Inline styles being blocked

If you cannot avoid inline styles, add 'unsafe-inline' to style-src directives. For better security, use the csp.policy_helper service to add hashes for specific inline styles.

script-src-attr or style-src-attr directive configured without fallback

The module will warn if *-attr or *-elem sub-directives are enabled without a corresponding fallback directive (script-src, style-src, or default-src). Enable the parent directive to ensure compatibility with browsers that don't support sub-directives.

No CSP header being sent

Check that at least one policy (Report-Only or Enforce) is enabled in configuration. Verify the user has permission to access the page and that caching is not interfering. Check that no other module or web server is removing the header.

Security Notes 6
  • The 'administer csp configuration' permission should only be granted to trusted administrators as misconfiguration can either break site functionality or weaken security
  • Avoid using 'unsafe-inline' and 'unsafe-eval' in production unless absolutely necessary, as they significantly weaken CSP protection
  • The 'strict-dynamic' keyword is not configurable through the UI as it requires hash or nonce implementation in application code
  • Hash sources in script-src or style-src may block functionality that relies on inline code - test thoroughly
  • The Report-Only header allows monitoring violations without blocking them - use this to develop your policy safely
  • CSP is a defense-in-depth measure and should not be the only security mechanism protecting your site