What CSP does
An enforced script policy can restrict the execution of injected scripts. It does not fix incorrect input handling or automatically make permitted scripts safe. Input validation, context-appropriate output encoding and safe DOM handling remain necessary. CSP is an additional layer of protection. W3C: introduction to CSP
The directives that actually apply are decisive. A policy containing only frame-ancestors controls who may embed the page; it does not restrict script execution. The presence of a header alone therefore says little about the overall scope of protection.
On narrow screens, scroll the table sideways.
| Term | Meaning | Limit |
|---|---|---|
enforce | A policy in the Content-Security-Policy header is enforced. | The browser blocks only actions that violate its effective rules. |
report | Content-Security-Policy-Report-Only lets you observe rules first. | This policy does not block anything; other enforced policies remain effective. |
AND | Multiple enforced policies apply together. | An additional permission does not override a restriction in another policy. |
The Wolf-Agents Web Security Check examines the CSP headers of the retrieved response. It does not execute every script, perform a penetration test or examine every subpage. Nonce generation, safe Trusted Types policies and browser compatibility need their own checks. An individual finding of this kind may already be enough to answer your initial configuration question.
Which XSS risks a script policy can limit
If an application has an XSS vulnerability, injected JavaScript could, for example, change page text, read input or access data available to JavaScript in that context. This can also affect forms and deceptive login screens. An HttpOnly cookie cannot be read directly by JavaScript; the attribute does not remove the other consequences of XSS. OWASP: Cross Site Scripting
An appropriate, enforced CSP can block the affected execution path before the injected script runs. This requires browser support for the relevant rule and no authorisation for the script through an effective source, nonce, hash or permitted dynamic loading path. Permitted but unsafe code remains a risk.
Conditional cases · no assessment of the whole application
Read the situation and the conclusion together
On narrow screens, scroll the table sideways.
| Situation | What it establishes |
|---|---|
| An XSS vulnerability exists and there is no effective script restriction. | CSP provides no additional barrier on this execution path. This does not yet establish an exploitable vulnerability on a particular page. |
| A script violates an enforced rule supported by the browser. | The browser blocks the action covered by that rule. This says nothing about every other execution path. |
| A CSP report arrives. | A reported rule violation can be investigated. The report alone does not prove an attack. |
| A header check finds a policy. | The examined response contains this configuration. This does not mean the whole application has passed acceptance testing. |
Distinguish HTTP headers, meta and multiple policies
The HTTP response header is the preferred delivery method. Check whether the application, web server and CDN each add a policy. What matters is the response that reaches the browser.
Two enforced policies are not combined into a more permissive shared allowlist. The following model deliberately contains a conflict:
Content-Security-Policy: connect-src 'none'
Content-Security-Policy: connect-src https://api.example.comA connection to https://api.example.com remains blocked by the first policy. The second cannot permit it. An additional Report-Only policy does not relax an existing restriction either. The example explains the rules; it is not a captured response from a measurement. W3C: multiple policies
A CSP can also appear in an HTML meta element. This method has limits: no Report-Only policy, no effective frame-ancestors, sandbox or report-uri directives, and no retrospective blocking of content before the meta element. A meta policy applies alongside other policies. Do not use it as an equivalent replacement for full header delivery. W3C: meta delivery
Introduce CSP in three steps
1. Deliver an initial policy without new enforcement
First identify the scripts, styles, images, fonts, API connections and embedded content that are needed. Also establish which component sets the headers. You can initially add a new or stricter policy as Report-Only while retaining an existing enforced baseline.
The following snippets illustrate the configuration format for Nginx and Apache respectively. They have not been run and are not universal production templates. example.com and /api/csp-report stand for a reporting destination you have set up; the header does not create a receiver.
Nginx: The appropriate http, server or location context and effective header inheritance must match how responses are served. always extends output to other response codes, but does not replace a check of the configuration structure. Nginx: headers module
add_header Reporting-Endpoints 'csp-endpoint="https://example.com/api/csp-report"' always;
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; report-uri /api/csp-report; report-to csp-endpoint" always;Apache: The snippet requires mod_headers. In .htaccess, the configuration must also be permitted there, for example through AllowOverride FileInfo. If the module is not loaded, the contents of IfModule are skipped. always and the normal header table are separate; check existing application and proxy headers for duplicates. Apache: Header directive
<IfModule mod_headers.c>
Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; report-uri /api/csp-report"
</IfModule>Both examples include broad image sources through https: and inline styles through 'unsafe-inline' in their rule models. This makes the explanation easier here, but is not a recommendation to adopt these permissions unchanged. 'unsafe-inline' is not set for scripts. Report-Only does not yet block the modelled violations.
2. Investigate violations and check functionality
Open your browser's developer tools, often through F12. Compare the CSP message with the delivered policy, affected page and triggering action. Check representative journeys, including login, forms and checkout where relevant; the home page alone is not enough.
Do not automatically add a reported domain. First decide whether the resource is needed, where it comes from and which directive actually applies.
On narrow screens, scroll the table sideways.
| Reported issue or resource | Next decision |
|---|---|
| Inline script | Does it belong to the application? If so, a specific nonce, a hash or a different way of including it may be suitable. Do not retrospectively authorise foreign or injected code. |
| External library | Check its purpose and exact loading source. A large CDN allowlist can permit more code than intended. |
| Google Fonts | Consider stylesheets and font files separately: fonts.googleapis.com and fonts.gstatic.com represent different resource roles, not a complete current provider guide. |
| Analytics or tag manager | Map scripts and network requests to the appropriate directives. Do not adopt wildcards such as *.google-analytics.com or *.googletagmanager.com solely because of a report. |
Central reporting needs the entire delivery path to work. report-to refers to a name in Reporting-Endpoints; report-uri is the older, deprecated method. If a browser supports report-to, it ignores report-uri in the same policy. The form you need depends on your target browsers and receiver. A console entry or a configured endpoint does not prove that a report was delivered. MDN: report-to
3. Enforce checked rules and retain a rollback path
Switch the new version only after the required functionality and reporting path have been checked within the intended scope. Save the previous configuration and establish who will restore the last known working policy if problems occur.
Content-Security-Policy-Report-Only → Content-Security-PolicyThe switch concerns the header name and the version actually delivered by the responsible components. Adding a header does not automatically replace existing policies. Continue meaningful functional tests and proportionate analysis of violations after the change. The rollout guide explains the decision points in more detail.
Read the main directives
This table is an orientation, not a ready-made policy. Values such as 'self', 'none', data: or https: must suit the intended action. 'self' refers to the page's own origin, not all its subdomains indiscriminately.
On narrow screens, scroll the table sideways.
| Directive | Area controlled | How to interpret possible values |
|---|---|---|
default-src | Fallback for covered fetch directives that are not set explicitly | For example 'self'; it does not replace every CSP directive. |
script-src | Script sources and associated execution rules | Nonces or hashes can authorise specific scripts; permission for a host is not a content check. |
style-src | Stylesheets and inline styles | For example 'self'; 'unsafe-inline' permits more inline styles and deliberately relaxes the policy. |
img-src | Images | 'self', data: or specific external sources; https: is broad permission for a scheme. |
font-src | Font files | Your own font sources and external sources that are actually needed. |
connect-src | Fetch, XMLHttpRequest, WebSocket and EventSource, among others | Required API and connection destinations; consider WebSocket paths explicitly. |
frame-ancestors | Which ancestors may embed the page | For example 'self' or 'none'; distinct from frame-src, which controls frames embedded by the page. |
object-src | Content loaded through object or embed | 'none' if these embeds are not needed. |
base-uri | Permitted base URL from a base element | 'self' or 'none' restrict changes to how relative URLs are resolved. |
form-action | Form submission destinations | For example 'self', provided no other destinations are needed. |
An explicit directive replaces the fallback to default-src for its area; it does not add to that directive's sources. When enforced, a present directive with an empty source list blocks the covered context and does not trigger fallback. script-src-elem can control script elements and script-src-attr event attributes more precisely. If absent, they fall back through script-src to default-src. For eval(), however, script-src applies, or default-src as its fallback. W3C: directives and fallback rules, JavaScript evaluation
frame-ancestors, base-uri and form-action have no such fallback to default-src. Nor is default-src itself mandatory: a targeted strict CSP can explicitly restrict scripts, objects and the base URL. This does not imply a restriction on every other resource type. W3C: strict CSP
For a particular message, always check the effective directive, not just the first line of your configuration.
Use nonces, hashes and strict-dynamic deliberately
A nonce marks selected script or style elements that you authorise. A new value must be generated each time a policy is transmitted; at least 128 bits from a cryptographically secure random number generator are recommended. The header and authorised elements of the same response must match. A static value to copy does not fulfil this purpose. For unchanging script content, hashes may better suit the delivery method. W3C: nonce requirements
Rule models · not an executed test
Two ways to authorise scripts
NONCE_VALUE is a visible placeholder, not a suitable production token.
Nonce and explicit sources
script-src 'nonce-NONCE_VALUE' 'self' cdn.jsdelivr.net unpkg.com cdnjs.cloudflare.com ajax.googleapis.com;A nonce and specific script sources form part of the effective source list.
Nonce or hash and strict-dynamic
script-src 'nonce-NONCE_VALUE' 'strict-dynamic';In supporting browsers, host and scheme permissions, 'self' and 'unsafe-inline' are ignored for this script evaluation.
Only in the second model, with browser support:
For example, through document.createElement('script').
document.write() is not part of this dynamic authorisation path. The permission does not check file content. MDN: strict-dynamic
strict-dynamic is therefore not a blanket improvement for every application. It transfers responsibility to the authorised loaders: if these use a script URL that an attacker can control, the policy may permit that load. Use the mechanism only if you need it and control the loading paths. Authorising a script guarantees neither harmless content nor the integrity of an external file. W3C: dynamic loading paths
Documented support for strict-dynamic starts with Chrome 52, Firefox 52 and Safari 15.4; support is also documented for Chromium-based Edge. These historical starting versions do not replace checks of your current target browsers and embedded browsers. MDN: compatibility data
For implementation details, read Nonces and caches.
Distinguish a security measure from evidence of compliance
The following references concern their respective scopes. They do not establish a uniform worldwide obligation to set a particular CSP header.
NIS2 and Germany's BSIG: Section 30 BSIG covers, among other matters, security in the acquisition, development and maintenance of IT systems. For entities within scope, section 38 requires management to implement and oversee risk management measures. A culpable breach of duty can give rise to liability towards the management's own entity. This does not create a general CSP certificate or automatic personal liability for a missing header. BSIG section 30, BSIG section 38
PCI DSS 4.0.1: For relevant payment pages, requirements 6.4.3 and 11.6.1 concern script authorisation, integrity, inventory and detecting tampering, among other things. CSP and Subresource Integrity can be parts of an appropriate approach. A header replaces neither the inventory nor the required ongoing controls or evidence within the specific assessment scope. PCI SSC: payment page security
Data protection: Article 32 GDPR requires technical and organisational measures that provide a level of security appropriate to the risk. CSP can limit certain browser risks; it does not establish data protection compliance on its own. EUR-Lex: GDPR, Article 32
The existing guides to the NIS2 checklist and management liability provide further context for Germany.
Choose the next step for your task
On narrow screens, scroll the table sideways.
| Your task | Further reading |
|---|---|
| Roll out new rules | Report-Only, checks and enforcement |
| Authorise specific scripts | Nonces |
| Investigate a message | Directives |
To start by assessing your domain's publicly accessible configuration, open the Web Security Check. Take account of its stated measurement scope; a CSP finding does not replace the functional and reporting checks described above.
Frequently asked questions
What is Content Security Policy (CSP)?
CSP sets rules for selected browser actions, such as script execution, resources and embedding. Its actual scope depends on the effective directives. It supplements secure programming and does not provide complete XSS protection.
Does CSP protect against every XSS attack?
No. Nonces or hashes can block unauthorised scripts, but do not automatically make permitted code safe. Trusted Types can provide additional protection for certain DOM interfaces, provided the browser enforces the requirement and the corresponding policies handle input safely.
Can CSP break my website?
Yes. An enforced policy can block resources or actions that the site needs. Try new rules with Report-Only and representative functional tests first. Policies that are already enforced remain active.
What is the difference between Report-Only and enforcement?
A Report-Only policy is monitored, but not enforced. An enforced policy blocks actions that violate its effective rules. Neither a week passing nor an absence of reports proves that the change works.
Do I need CSP if I already have a WAF?
A web application firewall examines traffic according to its rules; CSP enforces rules in the browser. The two can complement each other. Which measures are useful depends on your application. A WAF does not automatically make an appropriate CSP unnecessary, and does not guarantee that every attack will be detected.
Is CSP required for NIS2 compliance?
NIS2 does not name CSP as a universally mandatory header. An appropriate CSP can complement a technical measure. A header check does not establish that all legal or organisational requirements have been met.