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
Install
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
/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
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
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.
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.
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.
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.
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.
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