About Content Security Policy
What Is Content Security Policy?
Content Security Policy (CSP) is a web platform security feature that lets a site declare which sources the browser may use for scripts, styles, images, fonts, frames, network connections and other resources, and what inline code may do. A page that receives a policy applies it to everything it loads and runs; anything that does not match is blocked and can be reported.
CSP exists mainly to limit the damage of content injection, such as cross-site scripting (XSS), and to give sites control over third-party content. It is a defense-in-depth layer, not a substitute for fixing injection bugs. This CSP Analyzer, which you can also think of as a CSP checker, CSP validator and Content Security Policy analyzer, helps you read and review a policy; it cannot tell you whether the policy is sufficient for your application.
What Does a CSP Header Do?
The policy normally arrives in the Content-Security-Policy HTTP response header for each document. The browser parses it into directives and, as the page loads, checks every subresource request and several script behaviors against them. If a check fails, the resource is not loaded, the action is refused, a message appears in the console, and a violation report may be sent to an endpoint you configure.
Headers are not the only delivery method: a <meta http-equiv="Content-Security-Policy"> element works for many directives, but not for frame-ancestors, report-uri or sandbox. To see the headers your site actually sends, use the HTTP Security Headers Analyzer, which reviews CSP alongside HSTS, X-Content-Type-Options and other response headers, and the Redirect Chain Analyzer when you need to see what each hop in a redirect chain returns.
How to Read a CSP Policy
A policy is a list of directives separated by semicolons. Each directive is a name followed by zero or more values, usually source expressions:
default-src 'self'; script-src 'self' https://cdn.example.com; object-src 'none'
Read it one directive at a time. Here, anything without its own directive may load from the page's own origin; scripts may also load from cdn.example.com; and plugin content is blocked. The most common source expressions are:
'self'- the document's origin (scheme, host and port)'none'- nothing is allowedhttps://cdn.example.com- a specific host, optionally with port and pathhttps://*.example.com- matching subdomainshttps:ordata:- an entire scheme'nonce-...','sha256-...'- authorize specific inline content'unsafe-inline','unsafe-eval'- relax inline and eval restrictions'strict-dynamic'- trust scripts loaded by trusted scripts
The “Explain Policy” section of the tool rewrites each directive in plain English, and the Source Inspector breaks every source into scheme, host, port and path.
CSP Directives Explained
Directives fall into groups. The directive reference above covers each one in detail.
- Fetch directives control where resources load from:
default-src,script-src,style-src,img-src,font-src,connect-src,media-src,object-src,frame-src,worker-src,manifest-srcand the-elem/-attrvariants for script and style. - Document directives govern the document itself:
base-uriandsandbox. - Navigation directives govern where a page can send users or data and who can embed it:
form-actionandframe-ancestors. - Reporting:
report-uriandreport-to. - Other:
upgrade-insecure-requests,block-all-mixed-content(deprecated),require-trusted-types-forandtrusted-types.
Browser support is uneven for newer directives, so check the browsers you target. The analyzer reports an unrecognized directive as such rather than calling it invalid.
What Is default-src?
default-src is the fallback for most fetch directives. If img-src is absent, images follow default-src; if it is present, img-src applies and default-src is ignored for images. It does not apply to base-uri, form-action, frame-ancestors, sandbox or the reporting directives, so a policy that sets only default-src leaves those unrestricted. A specific directive replaces default-src for its resource type rather than adding to it, which is a frequent source of surprises.
What Is script-src?
script-src controls where JavaScript can come from and whether inline scripts and eval() are allowed. It is the directive most closely tied to XSS mitigation, so the analyzer checks it most closely: broad wildcards, https: and data: sources, HTTP sources, shared CDN hosts, 'unsafe-inline', 'unsafe-eval', nonces, hashes and 'strict-dynamic'. script-src-elem and script-src-attr can apply different rules to script elements and inline event handlers. Workers fall back to worker-src, then script-src.
What Does unsafe-inline Mean?
'unsafe-inline' allows inline code. In script-src that means inline <script> blocks, event-handler attributes and javascript: URLs, so injected markup can run script. In style-src it allows inline <style> blocks and style attributes, which is generally a smaller risk. The effect depends on the directive it appears in, and the analyzer words its findings accordingly.
It also depends on what else is in the list. Browsers that support nonces or hashes ignore 'unsafe-inline' when the same source list contains one, and browsers that support 'strict-dynamic' ignore it in script directives, so the keyword is sometimes kept deliberately as a fallback for old browsers.
What Does unsafe-eval Mean?
'unsafe-eval' allows eval(), new Function() and string arguments to setTimeout() and setInterval(). Some template engines, bundler development modes and older libraries rely on them. Its presence is a prompt to ask whether the dependency can be updated or precompiled; it does not mean the application is vulnerable. 'wasm-unsafe-eval' permits WebAssembly compilation without permitting eval().
What Is a CSP Nonce?
A nonce is a per-response random value. The server places it in the header (script-src 'nonce-r4nd0m') and on each allowed element (<script nonce="r4nd0m">). The browser runs only elements with a matching nonce, so an attacker who injects a script tag cannot guess it. That depends on the nonce being unpredictable and new on every response, which a static analyzer cannot verify, so a CSP nonce checker can confirm the syntax and flag values that look static or short, but not that your implementation is sound.
Content-Security-Policy: script-src 'nonce-4AEemGb0xJptoIGFP3Nd'; object-src 'none'; base-uri 'none'
What Is a CSP Hash?
A hash source allows an inline script or style by its digest: 'sha256-<base64>', with sha384 and sha512 also supported. It suits static inline snippets because any change to the content changes the digest. The analyzer is a CSP hash checker for syntax - the algorithm, base64 form and length - but it has no access to your page, so it cannot confirm that a hash matches deployed content. Browsers print the expected hash in their console message when a hash is missing.
What Is strict-dynamic?
'strict-dynamic' extends trust from a nonce- or hash-authorized script to the scripts it loads. In browsers that support it, host and scheme sources, 'self' and 'unsafe-inline' in that list are ignored, so the allowlist stops mattering and trust comes from the nonce or hash. Browsers without support ignore the keyword and fall back to the allowlist. Without any nonce or hash there is nothing to start the trust chain, so scripts may be blocked entirely. It is useful for applications whose trusted scripts load others dynamically, and is not required for every policy.
script-src 'nonce-4AEemGb0xJptoIGFP3Nd' 'strict-dynamic' https: 'unsafe-inline'
The example above is a known compatibility pattern: supporting browsers use the nonce and ignore the rest, while older browsers fall back to https: and 'unsafe-inline'.
CSP Report-Only vs Enforcing
Content-Security-Policy enforces: violations are blocked. Content-Security-Policy-Report-Only only reports: nothing is blocked, and violations show in the console and, if configured, at a report-uri or report-to endpoint. Report-Only is the safe way to test a new policy, and the analyzer labels the policy type at the top of its results so the two are never confused. A page can send both headers, and they are evaluated independently.
Common CSP Mistakes
- Writing
selfornonewithout quotes. Without quotes they are treated as host names, not keywords. - Assuming default-src controls base-uri, form-action or frame-ancestors; it does not.
- Adding 'unsafe-inline' to script-src to get a page working, which removes most of the protection.
- Allowing an entire public CDN or
https:in script-src, which allows many scripts you do not use. - Repeating a directive: browsers use the first occurrence and ignore the rest.
- Mixing up frame-src (what you embed) and frame-ancestors (who embeds you).
- Using a static nonce or a placeholder value copied from documentation.
- Setting frame-ancestors, report-uri or sandbox in a meta tag, where they are not supported.
- Deploying an enforcing policy without testing it in Report-Only first.
How to Fix CSP Errors
Open the browser console and read the violation message: it names the blocked URL and the directive that blocked it. Decide whether the resource is legitimate. If it is, add the exact origin to the specific directive that blocked it. If it is inline code, prefer moving it to a file or authorizing it with a nonce or hash over adding 'unsafe-inline'. If it is not legitimate, leave it blocked and find out where the request comes from. Iterate with a Report-Only header so visitors are not affected.
If your violation reports or console output contain tokens, user IDs or internal hostnames, remove them before sharing; the Log Sanitizer does that locally in your browser. Reports sent to report-uri are JSON, which the JSON Formatter can pretty-print for reading.
How to Create a CSP
A workable approach, which the generator above follows:
- List what the page actually loads: your own origin, CDNs, fonts, analytics, APIs, WebSockets and embeds.
- Start from a restrictive baseline (
default-src 'none'or'self') and add specific directives for each resource type. - Add
object-src 'none',base-uri,form-actionandframe-ancestors, which default-src does not cover. - Prefer nonces or hashes to 'unsafe-inline' for scripts.
- Deploy as Content-Security-Policy-Report-Only with a reporting endpoint, review the reports, then enforce.
On Apache you can set the header in configuration or .htaccess with Header set Content-Security-Policy "..."; the .htaccess Analyzer checks that file, and this tool accepts a pasted Header set line directly.
Header always set Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'"
CSP and XSS Protection
CSP can limit what injected content can do: with a strict policy, an injected inline script or a script from an unexpected origin is blocked. It does not remove the underlying bug, and policies that allow 'unsafe-inline', broad hosts or injectable endpoints give much less protection. Think of CSP as a second line of defense behind output encoding, input handling and safe templating. The analyzer shows what a policy permits; whether that is enough is a judgement about your application, and no tool can declare a site secure.
CSP behavior depends on browser support and the CSP specification level. The analyzer focuses on policy syntax and commonly implemented behavior and does not claim universal browser compatibility.