Fact-checked by Grok 2 weeks ago

Content Security Policy

Content Security Policy (CSP) is a declarative standard that enables developers to specify which sources of content are allowed to be loaded and executed by a for a given , thereby mitigating the risks of (XSS), , and other attacks. Introduced as a mechanism for defense-in-depth, CSP helps reduce the privileges of applications by restricting resource origins, inline scripts, and dynamic code execution, though it is not intended as a primary defense. CSP policies are delivered to browsers primarily through the Content-Security-Policy HTTP response header or via a <meta> element in documents, with an additional Content-Security-Policy-Report-Only mode available for monitoring violations without enforcement. These policies consist of one or more directives, such as script-src to control sources, img-src for images, and frame-ancestors to prevent by limiting framing contexts, each specifying allowed origins like 'self' for same-origin resources or specific URLs. Advanced features include nonces and hashes for allowing specific inline content, the strict-dynamic directive for trusted script loading chains, and reporting mechanisms via report-to to log policy violations for analysis. Originally proposed in 2011 and evolving through multiple levels, the current W3C Working Draft of CSP Level 3 (as of 2025) integrates with modern web standards like Fetch and Reporting APIs to provide extensible security controls. By enforcing upgrades and blocking mixed content, CSP enhances overall site integrity and supports compliance with security best practices across major browsers including , , and .

Overview

Purpose and Benefits

Content Security Policy (CSP) serves as an additional layer of security for web applications, enabling developers to detect and prevent specific types of attacks by instructing browsers on the permitted sources and execution of content. It primarily targets threats such as (XSS), where attackers inject malicious scripts into trusted sites; , which tricks users into unintended interactions via overlaid frames; and , including the execution of unauthorized dynamic code. By defining these restrictions, CSP acts as a proactive defense mechanism, complementing other browser security features like the . The core benefits of CSP include enforcing a of approved content sources, which blocks the loading of resources from unauthorized origins and thereby limits potential exploitation vectors. It further reduces the by defaulting to block inline scripts, inline styles, and dangerous functions like eval(), preventing the execution of embedded or dynamically generated malicious code. Additionally, CSP supports monitoring through violation reports, allowing site administrators to identify and address security issues without immediately enforcing blocks via a report-only mode. CSP mitigates XSS attacks by restricting script sources through directives like script-src, ensuring only vetted external scripts or hashed inline code can execute. For , the frame-ancestors directive prevents unauthorized embedding of the page in iframes from other domains. It also counters and injection risks via connect-src, which controls outbound connections to external endpoints, thereby containing potential breaches. The origins of CSP trace back to early discussions on web vulnerabilities, evolving as a response to the increasing prevalence of XSS incidents that exposed the limitations of existing defenses. Initial concepts for content restrictions were explored around 2007 by security researchers, leading to formal proposals and the first specification drafts by 2010. This development was driven by the need for a standardized, browser-enforceable policy to enhance .

History and Development

The concept of Content Security Policy (CSP) emerged in the mid-2000s as a response to growing concerns over (XSS) vulnerabilities in web applications. In 2005, developer Gervase Markham proposed an early framework called "Content Restrictions," which aimed to allow site owners to declare specific rules for resource loading via HTTP headers or meta tags, serving as a complement to server-side filtering. This idea built on prior discussions in the web security community, including suggestions from experts like around the same period, to provide granular control over content execution. Although initial proposals remained drafts, they laid the groundwork for more robust mechanisms to prevent injection attacks. Mozilla led the first practical implementation of CSP in 4, released in March 2011, introducing it as a server-delivered policy to whitelist approved sources for scripts, styles, and other resources. This beta feature quickly gained traction, with early adopters like integrating it to enhance site security without disrupting functionality. The effort was driven by 's security team, emphasizing its role in mitigating XSS by enforcing declarative policies at the browser level. Standardization efforts began under the W3C Security , which published CSP Level 1 as a Candidate Recommendation in November 2012, focusing on core directives for basic resource control. Level 2 advanced to Recommendation status in December 2016, expanding capabilities with features like nonce-based and hash-based whitelisting to safely permit inline content while blocking unauthorized injections. Level 3, initiated as a Working Draft in 2016, has continued evolving to address modern web complexities, including better integration with service workers and the ; the February 2025 Working Draft notably refined the strict-dynamic directive to simplify policy management for dynamic script loading and deprecated the report-uri directive in favor of the report-to mechanism aligned with the . As of November 2025, Level 3 remains a Working Draft, reflecting ongoing refinements. The development of CSP has been a collaborative process led by the W3C Web Application Security Working Group, with key contributions from browser vendors including , which pioneered implementation, and , which influenced extensions for broader adoption across Chrome and other engines. This vendor-driven evolution has positioned CSP as a foundational web security standard, iteratively improving its effectiveness against evolving threats like XSS.

Technical Specifications

Core Directives

The core directives in Content Security Policy (CSP) form the foundational controls for restricting how resources are loaded and executed on a , thereby mitigating risks such as (XSS) and other injection attacks. These directives specify allowed sources for various types of content, with each directive targeting a specific category of resource fetch or execution. By defining granular policies, developers can enforce a , allowing only trusted origins while blocking potentially malicious ones. CSP directives follow a consistent syntax: directive-name source-list;, where the directive-name identifies the resource type (e.g., script-src), and the source-list enumerates allowed origins, keywords, or mechanisms like nonces and hashes. The source-list is a serialized comma-separated list of source expressions, which can include keywords such as 'self' (matching the document's origin), specific schemes (e.g., https:), hostnames (e.g., https://example.com), or special values like 'none' to block all sources. If a directive is absent, it falls back to the default-src directive, providing a policy that applies broadly unless overridden. The default-src directive serves as the fallback for all other fetch directives not explicitly defined in the policy, establishing a default source list for resource loading. For instance, default-src 'self'; would restrict unspecified resources to the same as the protected document. This directive is crucial for creating comprehensive policies, as it ensures consistent enforcement across resource types without requiring every directive to be specified. The script-src directive governs the sources from which executable scripts, including JavaScript and WebAssembly modules, can be loaded and executed. It controls both external script fetches and inline script elements or event handlers; by default, it blocks inline scripts unless 'unsafe-inline' is included in the source-list, which permits them but reduces security by allowing potential XSS vectors. Additionally, 'unsafe-eval' allows the use of eval() and similar functions, though it is strongly discouraged due to the risk of code injection. An example policy might read: script-src 'self' https://trusted-scripts.example.com;, limiting scripts to the document's origin and a specific external domain. The style-src directive restricts the sources of stylesheets and inline styles, preventing the loading of untrusted CSS that could alter page appearance or enable attacks like UI redressing. Similar to script-src, it blocks inline styles unless 'unsafe-inline' is specified, and it also gates dynamic CSS insertion via 'unsafe-eval'. For example: style-src 'self' https://styles.example.com;. The img-src directive specifies valid sources for images and favicons, controlling fetches with a destination of "image" to block malicious or unwanted image loads. It applies to elements like <img> and <picture>, falling back to default-src if omitted. The connect-src directive limits the URLs to which script interfaces, such as XMLHttpRequest, fetch(), WebSockets, or EventSource, can connect, thereby containing data exfiltration risks. For instance: connect-src 'self' wss://api.example.com;. The child-src directive governs the creation of nested browsing contexts (such as iframes and frames) and Worker execution contexts, controlling the sources from which these child resources can be loaded. It serves as a fallback for frame-src and worker-src if those directives are absent. The frame-src directive defines allowed sources for nested browsing contexts, such as those created by <frame> or <iframe> elements. Introduced in CSP Level 2 and undeprecated in Level 3, it defers to child-src if present, or to default-src otherwise. The font-src directive controls the sources for font resources, including web fonts loaded via @font-face, to prevent unauthorized font fetches. It targets requests with a destination of "font". The object-src directive restricts sources for plugin-related elements like <object>, <embed>, and <applet>, often set to 'none' to fully disable plugins and mitigate risks from legacy content like Flash. CSP Level 2 introduced the frame-ancestors directive, which specifies valid parent origins that may embed the protected resource in a frame, iframe, object, embed, or applet, primarily to defend against clickjacking attacks. Unlike other directives, it does not fall back to default-src and defaults to allowing all origins (*) if unspecified; its syntax is frame-ancestors source-list;, where the source-list uses ancestor sources like schemes or hosts. In CSP Level 3, the worker-src directive was added to govern the sources of Worker, SharedWorker, and ServiceWorker scripts, deferring to child-src, then script-src, and finally default-src if absent. This ensures secure execution contexts for background scripts, with syntax worker-src source-list;.

Source Expressions and Values

In Content Security Policy (CSP), source expressions define the allowable origins, schemes, or mechanisms for loading resources under a given directive, such as script-src or style-src. These expressions form a comma-separated source list appended to the directive, enabling fine-grained control over resource fetching to mitigate risks like (XSS). For instance, a policy might specify script-src 'self' https://example.com to allow scripts only from the document's origin or a specific domain. The syntax for source lists follows a serialized format where multiple expressions are separated by commas, and each directive's list is terminated by a semicolon before the next directive. Valid expressions include the keyword 'none', which blocks all resources for that directive, as in img-src 'none'. Common keywords encompass 'self', matching resources from the same origin (including upgrades to https: or wss:), and 'unsafe-inline', which permits inline scripts or styles but increases XSS vulnerability. Another keyword, 'unsafe-eval', allows dynamic code execution via functions like eval() or new Function(), though it is discouraged for security reasons. Source expressions can specify URL schemes and hosts for precise allowlisting. Schemes like http:, https:, data:, and blob: match resources using those protocols; for example, data: allows inline data URIs. Hosts support full domains (e.g., example.com), subdomain wildcards (e.g., *.example.com to include subdomains but not the apex), and optional port specifications (e.g., https://example.com:443). Internationalized domain names must use Punycode encoding, and IP addresses are restricted to loopback like 127.0.0.1. These constructs ensure resources load only from trusted locations without broad permissions. Advanced values provide mechanisms for safer inline content inclusion. Nonces are random, base64-encoded generated per request, prefixed with 'nonce-' (e.g., 'nonce-ch4hvvbHDpv7xCSvXCSvXCs3BrNggHdTzxUA'), matching only elements with a corresponding nonce attribute to allow specific inline scripts or styles without exposing them to injection. Hashes use cryptographic digests prefixed with 'sha256-', 'sha384-', or 'sha512-' followed by a base64-encoded value (e.g., 'sha256-abcd1234...'), verifying the exact content of inline elements or external resources with integrity attributes. The Level 3 keyword 'unsafe-hashes' extends hash matching to event handlers, style attributes, and javascript: navigations, offering partial inline allowance while blocking broader inline execution. CSP Level 3 introduces 'strict-dynamic', a keyword that simplifies deployment for modern applications using script bundlers. When present in script-src, it enables parser-inserted scripts (e.g., via <script src> tags) to dynamically load further scripts without explicit allowlisting, while blocking inline and -based execution unless combined with nonces or hashes. This parser-based approach trusts the initial trusted scripts to vet subsequent loads, reducing complexity for complex applications.

Delivery and Enforcement

Policy Delivery Methods

Content Security Policy (CSP) policies are primarily delivered to web browsers via the HTTP response header named Content-Security-Policy, which carries a serialized policy string defining the allowed resources and behaviors for the response. This method allows administrators to specify policies dynamically for each request, applying to the entire and its loaded resources, such as scripts, images, and stylesheets. For instance, a might include Content-Security-Policy: default-src 'self'; script-src 'self' example.com in the HTTP response to restrict sources accordingly. An alternative delivery mechanism uses an within the document's <head> section, formatted as <meta http-equiv="Content-Security-Policy" content="policy-string">. This approach is particularly useful for static sites or single-page applications where server-side headers cannot be set, but it is limited to non-navigational contexts and must appear early in the document to affect subsequent content parsing. Notably, meta-delivered policies do not support the report-only mode in any browser, as this requires the dedicated Content-Security-Policy-Report-Only HTTP header. When multiple CSP policies are delivered—via headers or a combination of headers and meta tags—browsers collect them into a single CSP list and enforce the most restrictive intersection of directives, regardless of delivery order or method. For example, if one policy allows scripts from 'self' and another from https://trusted.com, the effective policy permits only sources allowed by both. The HTTP header method scopes policies to the full response, including embedded resources, while the meta tag applies to the parsing of the containing and subsequent resource loads and executions. CSP policies cannot be delivered or modified via , ensuring they remain tamper-resistant against client-side alterations.

Enforcement and Parsing Rules

Browsers parse Content Security Policy (CSP) headers or meta elements by first decoding the serialized policy string into a policy object, specifying its source (such as "header" or "meta") and disposition ("enforce" or "report-only"). The parsing algorithm splits the policy on semicolons to separate directives, strips leading and trailing whitespace from each resulting token, and identifies the directive name in a case-insensitive manner. Duplicate directives are ignored, and the values for each directive are further split on whitespace (spaces or tabs) to form a source list, which consists of source expressions like keywords, schemes, hosts, nonces, or hashes. Schemes in source expressions are normalized to lowercase, hosts are matched case-insensitively after lowercasing, and ports are omitted unless explicitly specified, ensuring consistent evaluation against requested resources. If parsing fails due to invalid syntax, the policy is treated as empty and has no effect. In the enforcement model, user agents apply policies to block potentially unsafe resource loads, executions, and navigations during document creation, script execution, and fetch operations. For resource requests, a pre-request check evaluates whether the requested matches the relevant directive's source list (such as script-src for scripts); if no match is found, the request is blocked before it is sent. Post-response checks similarly inspect loaded resources, blocking their use if they violate the policy in enforce mode, while report-only mode logs violations without blocking. Inline scripts and styles are blocked by default unless explicitly allowed via 'unsafe-inline', a matching attribute, or a valid in the source list; this prevents execution of embedded code without external file loads. The use of eval() and similar functions is blocked if 'unsafe-eval' is absent from script-src (or default-src as fallback), resulting in an EvalError to mitigate dynamic . Directive inheritance relies on the default-src directive, which provides a fallback source list for any fetch directive (e.g., img-src, style-src) that is not explicitly defined in the policy. If default-src is specified, its values cascade to unspecified directives, but an explicitly stated directive overrides this fallback entirely. Document-level policies apply to all subresources loaded by the document, such as images or scripts, unless a more specific directive governs the resource type. Edge cases in enforcement include handling nested browsing contexts, where the parent document's or directive controls whether the or can be loaded by checking its URL against the source list before occurs, and the child document enforces its own policy delivered via its response. Additionally, the directive integrates with CSP by deriving HTML sandboxing flags from its value tokens (e.g., 'allow-scripts' or 'allow-same-origin'), enforcing isolated execution environments that restrict features like popups, forms, or script execution independently of other CSP rules. In report-only mode, these edge cases trigger violation reports without altering behavior, aiding policy debugging.

Reporting and Monitoring

Violation Reporting Directives

Violation reporting directives in Content Security Policy (CSP) enable user agents to notify designated endpoints when a policy violation occurs, allowing server administrators to monitor and analyze potential security issues without altering the enforcement behavior of the policy. These directives facilitate the collection of data on blocked resources or actions, which can help refine policies over time. Reports are generated asynchronously and sent via HTTP POST requests to specified URIs, supporting both enforcing and report-only modes in a single policy. The report-uri directive, introduced in CSP Level 1 and carried forward to Level 2, specifies one or more URIs to which violation reports should be sent. When a violation is detected, the user agent constructs a JSON-formatted report and delivers it via HTTPS POST to each listed URI, using a Content-Type of application/json. However, report-uri has been deprecated in CSP Level 3 in favor of the more flexible report-to directive, though it remains supported for backward compatibility in most browsers. The report-to directive, defined in CSP Level 3, replaces report-uri by referencing named endpoint groups configured via the Reporting-Endpoints HTTP response header, integrating directly with the . For example, a policy might include report-to csp-endpoint;, where csp-endpoint is a group name defined in the header as Reporting-Endpoints: csp-endpoint="https://example.com/reports". This allows for multiple endpoints within a group, enabling load balancing or specialized routing for different report types, with reports queued and sent asynchronously to ensure they do not block page loading. Endpoint configuration requires all URIs to use for security, and reports are delivered as requests with Content-Type: application/reports+json in Level 3 implementations. If no valid endpoints are available, reports are discarded silently to avoid impacting performance. Violation reports in CSP Level 3 use a standardized structure defined by the CSPViolationReportBody , serialized within a broader report object that includes metadata like type: "csp-violation" and age. The core body contains the following key fields:
  • documentURL: The URL of the document in which the violation occurred.
  • referrer: The referrer URL at the time of the violation.
  • blockedURL: The URL of the resource that was blocked (or "inline" for inline violations, or "eval" for eval-based ones).
  • effectiveDirective: The directive whose enforcement triggered the violation.
  • originalPolicy: The full original CSP policy string.
  • disposition: Either "enforce" or "report", indicating the policy mode.
  • statusCode: The HTTP status code of the blocked request, if applicable (e.g., 0 for network errors).
  • sourceFile, lineNumber, and columnNumber: Location details for the violating script or style, if available.
  • sample: A snippet of the violating inline code, truncated to 40 characters for privacy.
This format evolved from the hyphenated keys (e.g., blocked-uri) used in earlier levels to camelCase for consistency with modern web standards. CSP Level 3 enhancements emphasize scalability through the Reporting API integration, allowing dynamic endpoint management and reducing reliance on static URI lists, which improves monitoring in complex web applications. The deprecation of report-uri encourages adoption of report-to to leverage features like report filtering and persistence across navigations.

Report-Only Mode

Content Security Policy (CSP) report-only mode provides a mechanism for web developers to monitor and test security policies without enforcing them, allowing sites to continue operating normally while collecting data on potential violations. This mode uses the Content-Security-Policy-Report-Only HTTP response header to define a policy that instructs user agents to report violations as they would in enforcing mode, but without blocking any resources or execution. The syntax for the report-only header mirrors that of the enforcing Content-Security-Policy header, consisting of one or more serialized policy directives separated by semicolons, with a required reporting directive such as report-to to specify the for violation reports. For example, a basic policy might be delivered as Content-Security-Policy-Report-Only: script-src 'self'; report-to csp-[endpoint](/page/Endpoint), where script-src 'self' restricts scripts to the same , and report-to csp-[endpoint](/page/Endpoint) directs reports to a defined via the Reporting API. Unlike the enforcing header, the report-only variant is not supported via HTML <meta> elements, limiting its delivery to HTTP headers. Common use cases for report-only mode include initial policy testing to assess impact without disrupting site functionality, gradual rollout of stricter policies by monitoring real-user behavior over time, and identification of false positives in existing policies that might otherwise break legitimate features. By deploying this mode, developers can iteratively refine CSP configurations based on collected reports, ensuring a smooth transition to enforcement. In terms of behavior, report-only policies are parsed and applied similarly to enforcing ones during resource fetching and execution contexts, but violations trigger reports—such as JSON payloads detailing the blocked URI, policy, and violation type—without preventing the resource from loading or executing, providing a safe fallback to normal operation. These reports follow the same delivery mechanisms as in enforcing mode, including the use of the Reporting-Endpoints header for endpoint configuration. The sandbox directive is ignored in report-only mode, as it inherently requires enforcement to be effective. Limitations of report-only mode include its lack of enforcement, which means it offers no immediate protection against attacks, and the potential for generating a high volume of reports if the policy is overly restrictive, overwhelming monitoring endpoints. Additionally, while widely supported in modern browsers since around , the absence of <meta> tag support restricts deployment in certain static or serverless environments.

Limitations and Challenges

Known Bypasses and Vulnerabilities

One notable historical bypass technique emerged in , involving the exploitation of endpoints on whitelisted domains. Attackers could inject malicious via the callback parameter in JSONP responses from trusted sources, enabling despite CSP restrictions on script sources. This affected a significant portion of policies, with analysis showing that 75.81% of observed CSP whitelists were insecure due to such endpoints on 194,908 domains. In 2016, a for -based CSP policies using DOM XSS involved exfiltrating the value through CSS-based bruteforcing of the tag content, allowing attackers to inject and execute scripts with the stolen . This highlighted the need for cryptographically secure, per-request to prevent or leakage. By 2017, injections into vulnerable third-party libraries became a prominent vector. Script gadgets in popular frameworks like 1.x and allowed attackers to repurpose existing, CSP-approved code for arbitrary execution, bypassing , hashes, and whitelists. Such gadgets were prevalent, appearing in 20% of the Top 5,000 sites and enabling successful bypasses in 53.13% of tested framework-mitigation combinations. Recent developments in revealed a sophisticated injection bypass for nonce-based policies, disclosed in July. This combined browser caching (bfcache and disk ) with CSS-based extraction from tags and CSRF to reuse leaked nonces across sessions, allowing malicious execution. The technique exploited manipulation via Network Isolation Keys and parameters to deliver payloads without direct nonce generation flaws. In September 2025, a CSP bypass vulnerability (CVE-2025-58351) was disclosed in , an open-source . Starting from version 0.72.0, the optional local feature allowed attackers to bypass CSP as well as Content-Type restrictions, potentially enabling further attacks like XSS in self-hosted environments. Weaknesses in the 'strict-dynamic' directive have also surfaced with scripts. While 'strict-dynamic' enables trusted (nonced or hashed) scripts to dynamically load sub-resources, it ignores parser-inserted scripts lacking proper nonces or hashes, potentially blocking legitimate code or allowing unsafe-eval usage in older libraries that violate modern CSP expectations. This can lead to incomplete protection if code relies on broad whitelists or inline execution not aligned with . Common vulnerability types include misconfigurations, such as overly permissive 'unsafe-inline' in script-src, which negates CSP's core benefits by allowing arbitrary inline scripts and exposing sites to XSS. Browser bugs have occasionally enabled bypasses; for instance, a 2020 flaw (CVE-2020-6519) allowed attackers to inject malicious via an iframe's srcdoc attribute, bypassing policy enforcement. Additionally, browser extensions can inject content outside CSP enforcement, as they operate at a higher privilege level and modify the DOM post-policy application. To mitigate these issues, developers should employ 'strict-dynamic' alongside Trusted Types to sanitize DOM sinks and prevent injection-based nonces leaks. Regular nonce rotation per request, using cryptographically secure random values, counters reuse attacks. Auditing third-party scripts for gadgets, JSONP endpoints, and vulnerabilities ensures whitelists remain secure, with tools like script hashing or nonces applied to legacy integrations.

Exemptions and Edge Cases

Browser extensions and add-ons are typically exempt from enforcement of a web page's Content Security Policy (CSP) to maintain their intended functionality. Content scripts injected by extensions execute within the page's but bypass the page's CSP restrictions, as they originate from the extension's privileged environment rather than the document itself. This allows extensions, such as ad blockers, to insert scripts or modify the DOM in ways that would violate the site's policy if performed by page content. In legacy browsers like and 11, CSP support is severely limited, with enforcement restricted to the directive delivered exclusively via the deprecated X-Content-Security-Policy header. All other CSP directives, including script-src and default-src, are ignored, preventing full policy application and leaving these browsers vulnerable to attacks that CSP aims to mitigate in modern environments. The tag method for delivering CSP also encounters edge cases, particularly in certain navigation scenarios. Policies defined in a are not applied to preceding inline content in the and are ignored for navigations that do not trigger full , such as fragment identifier changes or loads from the browser's back-forward cache. Additionally, directives like frame-ancestors, , and report-uri are not supported via tags, limiting their utility compared to HTTP header . Service workers are partially exempt from standard CSP enforcement in that their initial script registration is governed by the worker-src directive (or fallback to child-src or -src), but once active, they can intercept fetch requests and responses, potentially serving resources without adhering to the originating document's CSP headers. This interception capability allows service workers to or modify content in ways that circumvent per-request policy checks, though the worker's own code remains subject to the policy under which it was registered. Top-level navigations reset CSP policies by loading a new with its own derived from the response headers or elements, discarding the previous 's entirely. This behavior ensures between distinct origins or pages but can lead to unexpected inheritance gaps during cross-origin or same-site transitions without proper server configuration. To address these exemptions, extension developers must define and comply with the extension's dedicated CSP in the manifest.json file, using directives like script-src 'self' to restrict their own resources without relying on page policies. For legacy browsers, fallback strategies include providing alternative , such as validation or no-script fallbacks, alongside monitoring for unsupported CSP via report-only modes in compatible environments.

Adoption and Implementation

Browser Support and Compatibility

Content Security Policy (CSP) enjoys extensive support in modern web browsers, enabling widespread adoption for mitigating and other injection attacks. Full implementation of CSP Level 1 and Level 2 directives began with Chrome version 25 in July 2012, Firefox version 23 in August 2013, Safari version 10 in September 2016, and version 12 in July 2015. By 2025, these levels achieve near-universal coverage in current browser versions, encompassing over 95% of global and all major desktop and mobile platforms excluding legacy systems. Partial support persists in older browsers, notably and 11, which recognize only the sandbox directive through the non-standard X-Content-Security-Policy header and lack broader directive enforcement. Similarly, pre-2016 mobile browsers—such as on versions below 10 or early for —offer incomplete compatibility, particularly for advanced Level 3 features like strict-dynamic, which requires parser-inserted scripts with nonces or hashes for . Support varies by CSP level, with Levels 1 and 2 fully integrated across , , , , and in versions dating back over a . Level 3 enhancements, however, rolled out more gradually: the strict-dynamic source expression for script-src arrived in 52 (September 2016), 52 (March 2017), 79 (January 2020), and 15.4 (March 2022). The report-to directive, which leverages the for violation endpoints, is implemented in 84+ (July 2020) and 84+ (August 2020), but remains unsupported in (up to version 130 in 2025) and , where the report-uri directive persists as the fallback. No polyfills exist for CSP, as it relies on native enforcement for efficacy, precluding JavaScript-based emulation. Compatibility testing is recommended via tools like Can I Use, which aggregates real-time usage data and feature flags across .
BrowserCSP Level 1/2 Full SupportLevel 3 Example: strict-dynamicLevel 3 Example: report-to
25+ (2012)52+ (2016)84+ (2020)
23+ (2013)52+ (2017)Not supported
10+ (2016)15.4+ (2022)Not supported
12+ (2015)79+ (2020)84+ (2020)
IEPartial (10/11, sandbox only)Not supportedNot supported

Best Practices and Complementary Measures

Implementing Content Security Policy (CSP) effectively requires a phased approach to deployment, beginning with the report-only mode to evaluate potential impacts without disrupting functionality. This mode, delivered via the Content-Security-Policy-Report-Only HTTP header, allows monitoring of violations through endpoints specified in the report-to directive, enabling identification and resolution of issues before full enforcement. To maximize security, policies should minimize or eliminate the use of unsafe-inline and unsafe-eval keywords in directives like script-src and style-src, as these can introduce (XSS) risks by permitting inline scripts or dynamic code evaluation. Instead, for dynamic content, employ —unique, per-request random values added to script and style elements (e.g., <script nonce="random-value">) and referenced in the (e.g., script-src 'nonce-random-value'). Nonces are preferred over hashes for performance in dynamic environments, as hashes require computing and including digests for each inline resource, which can increase page load times, whereas nonces are generated server-side without client-side computation. For static content, hashes (e.g., script-src 'sha256-base64hash') provide a viable alternative. Additionally, incorporating 'strict-dynamic' into nonce- or hash-based script-src policies allows trusted scripts to dynamically load further resources without explicit whitelisting, simplifying management for modern applications while maintaining boundaries. CSP should be complemented by other security headers for layered defense. HTTP Strict-Transport-Security (), via the Strict-Transport-Security header, enforces HTTPS connections and can integrate with CSP's upgrade-insecure-requests directive to mitigate mixed-content issues. For clickjacking prevention, while CSP's frame-ancestors directive (e.g., frame-ancestors 'none') has largely superseded X-Frame-Options, the latter remains useful in legacy contexts or as a fallback where CSP support is incomplete. Subresource Integrity (), applied through the integrity attribute on script and stylesheet elements (e.g., <script src="https://example.com/script.js" integrity="sha256-...">), verifies the integrity of third-party resources against tampering, providing an additional check beyond CSP's source restrictions. Optimization involves tailoring policies for granularity, such as defining page-specific directives (e.g., stricter script-src for administrative pages versus broader allowances for public ones) rather than relying solely on a global default-src. Automated tools facilitate this: the CSP Evaluator from analyzes policies for weaknesses like overly permissive sources, while browser DevTools and services like report-uri.com generate hashes and monitor violations to refine policies iteratively. Continuous monitoring in report-only mode helps detect and address false positives, such as legitimate inline styles blocked by strict rules, ensuring usability without compromising protection. As of 2025, integrating CSP with the (now at Level 3) enhances DOM XSS prevention by enforcing typed, sanitized inputs to dangerous DOM sinks like innerHTML. The CSP require-trusted-types-for directive (e.g., require-trusted-types-for 'script') mandates that scripts adhere to defined policies, blocking untrusted string insertions and complementing CSP's execution controls for a more robust defense against client-side injection attacks.

References

  1. [1]
    Content Security Policy Level 3 - W3C
    This document defines Content Security Policy (CSP), a tool which developers can use to lock down their applications in various ways, mitigating the risk of ...Framework · Policy Delivery · Integrations · Content Security Policy...
  2. [2]
    Content Security Policy (CSP) - HTTP | MDN
    ### Summary of Content Security Policy (CSP) from MDN
  3. [3]
    Content Security Policy 1.0 Lands In Firefox - The Mozilla Blog
    Jun 11, 2013 · The idea of a document being able to specify content restrictions dates back to at least 2007, when it was discussed by both Gervase Markham of ...
  4. [4]
    [PDF] Reining in the Web with Content Security Policy - Conference
    Apr 30, 2010 · Our proposed scheme is intended to provide a site's ad- ministrators control over behavior and appearance of their site S with a rule set that ...Missing: 2004 | Show results with:2004
  5. [5]
    Content Security Policy Level 2 - W3C
    Dec 15, 2016 · This document defines Content Security Policy, a mechanism web applications can use to mitigate a broad class of content injection vulnerabilities.Key Concepts and Terminology · Policy Delivery · Syntax and Algorithms · Directives
  6. [6]
    Mitigating XSS Attacks With Content Restrictions | Hacking for Christ
    Mar 29, 2005 · ... Content Restrictions“, presents the draft specification of a way for a site designer to explain his state of mind to the user agent by ...
  7. [7]
    Firefox Aims to Unplug Scripting Attacks - MIT Technology Review
    Jun 29, 2009 · The new security measure is based on suggestions made by Web-security specialist Robert Hansen back in 2005. ... Content Restrictions. “The ...Missing: proposal | Show results with:proposal
  8. [8]
    Creating a Safer Web with Content Security Policy - The Mozilla Blog
    Mar 22, 2011 · One of the new features in Firefox 4 that we are very excited about is Content Security Policy, which is a mechanism that works behind the ...
  9. [9]
    Content Security Policy 1.0 publication history | Standards - W3C
    Content Security Policy 1.0 publication history ; 19 February 2015, Retired ; 15 November 2012, Candidate Recommendation Snapshot ; 10 July 2012, Last Call Working ...
  10. [10]
    Content Security Policy Level 2 publication history | Standards - W3C
    Content Security Policy Level 2 publication history. Date, Status. 15 December 2016, Recommendation. 8 November 2016, Proposed Recommendation.
  11. [11]
    Content Security Policy Level 3 publication history | Standards - W3C
    Content Security Policy Level 3 publication history ; 21 February 2024, Working Draft ; 23 January 2024, Working Draft ; 15 January 2024, Working Draft ; 6 December ...
  12. [12]
  13. [13]
  14. [14]
  15. [15]
  16. [16]
  17. [17]
  18. [18]
  19. [19]
  20. [20]
  21. [21]
  22. [22]
  23. [23]
  24. [24]
  25. [25]
  26. [26]
  27. [27]
  28. [28]
  29. [29]
  30. [30]
  31. [31]
  32. [32]
  33. [33]
  34. [34]
    Reporting API - W3C
    Jun 11, 2025 · As a concrete example, Content Security Policy grants something like herd immunity to cross-site scripting attacks by alerting developers about ...
  35. [35]
  36. [36]
    Content-Security-Policy-Report-Only header - HTTP - MDN Web Docs
    Jul 4, 2025 · This header allows you to test or repair violations before a specific Content-Security-Policy is applied and enforced. The CSP report-to ...
  37. [37]
  38. [38]
  39. [39]
    [PDF] CSP Is Dead, Long Live CSP! On the Insecurity of Whitelists and the ...
    ABSTRACT. Content Security Policy is a web platform mechanism de- signed to mitigate cross-site scripting (XSS), the top security.
  40. [40]
    How to bypass CSP nonces with DOM XSS - sirdarckcat
    Dec 27, 2016 · This blog post talks about CSP nonce bypasses. It starts with some context, continues with how to bypass CSP nonces in several situations and concludes with ...
  41. [41]
  42. [42]
  43. [43]
    Content Security Policy - OWASP Cheat Sheet Series
    A strong CSP provides an effective second layer of protection against various types of vulnerabilities, especially XSS. Although CSP doesn't prevent web ...
  44. [44]
    Google Chrome Bug Could Let Hackers Bypass CSP Protection
    Aug 11, 2020 · A zero-day flaw in Chromium-based web browsers for Windows, Mac and Android that could have allowed attackers to entirely bypass Content Security Policy (CSP) ...
  45. [45]
    Mitigate cross-site scripting (XSS) with a strict Content Security ...
    Sep 13, 2024 · This page explains how to use a CSP based on nonces or hashes to mitigate XSS, instead of the commonly used host-allowlist-based CSPs that often leave the page ...Missing: clickjacking | Show results with:clickjacking
  46. [46]
    Content Security Policy - Mozilla - MDN Web Docs
    Jul 17, 2025 · Content Security Policy (CSP) is a mechanism to help prevent websites from inadvertently executing malicious content.
  47. [47]
    Content Security Policy 1.0 | Can I use... Support tables ... - CanIUse
    "Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile web browsers.
  48. [48]
    Manifest - Content Security Policy | Chrome Extensions
    Feb 13, 2024 · Developers may add or remove rules for their extension, or use the minimum required content security policy, to fit the needs of their project.Default Policy · Minimum and customized... · Extension Pages Policy
  49. [49]
  50. [50]
    strict-dynamic Explained - Content Security Policy
    The strict-dynamic source list keyword allows you to simplify your CSP policy by favoring hashes and nonces over domain host lists. A strict-dynamic Example.Missing: weaknesses legacy
  51. [51]
    "strict-dynamic" | Can I use... Support tables for HTML5, CSS3, etc
    "Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile web browsers.
  52. [52]
    report-to | All you need to know - CentralCSP
    Limited Browser Support: The report-to directive is not implemented in all major browsers yet. For maximum compatibility, it's recommended to use report-uri ...
  53. [53]
    Content Security Policy Level 2 | Can I use... Support ... - CanIUse
    "Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile web browsers.
  54. [54]
    CSP Evaluator
    CSP Evaluator allows developers and security experts to check if a Content Security Policy (CSP) serves as a strong mitigation against cross-site scripting ...Missing: optimization | Show results with:optimization
  55. [55]
    Trusted Types - W3C
    Oct 28, 2025 · Policies allows the authors to specify custom, programmatic rules that Trusted Types must adhere to.
  56. [56]
    Content-Security-Policy: require-trusted-types-for directive - HTTP
    Jul 4, 2025 · The HTTP Content-Security-Policy (CSP) require-trusted-types-for directive instructs user agents to control the data passed to DOM XSS sink functions.