🔧 Operation
📝 Directives
One row per directive. Tokens are whitespace-separated. The quick toggles add or remove a common
keyword. Use the curly placeholder {NONCE} inside a 'nonce-…' token for the
server template to fill in per request.
📝 CSP header value
Paste only the value (the right-hand side of Content-Security-Policy:). Newlines are
tolerated.
📤 Header value
HTML meta tag
📤 Parsed directives
📤 Analysis
Found {{ currentWarnings.length }} item(s).
⚠️ Warnings
ℹ️ About CSP Generator
What is a Content Security Policy?
A Content Security Policy (CSP) is an HTTP response header that tells the browser which sources of content (scripts, styles, images, fonts, frames, workers, connections, and form targets) are allowed to load or run on a page. It is a browser-enforced mitigation for cross-site scripting (XSS), data-injection bugs, mixed-content mistakes, and clickjacking: when a fetch, inline script, navigation, or embedding attempt does not match the policy, the browser blocks it before the page can use it.
The policy is expressed as a semicolon-separated list of directives, each followed by a source
list. This tool builds policies from a structured directive list, parses an existing header back into
structured form, and analyses any policy for configuration mistakes that weaken protection, such as
'unsafe-inline', broad wildcards, missing default-src, missing
frame-ancestors, and 'strict-dynamic' without a nonce or hash. CSP complements
output encoding, dependency hygiene, and framework-level XSS defenses; it does not prove a page is free of
injection bugs. All processing runs in your browser; the API endpoint below runs the exact same TypeScript
module so server and browser checks stay consistent.
Directives at a glance
| Directive | Fetch direction | Controls |
|---|---|---|
default-src | fallback | Default when a more specific fetch directive is not set. |
script-src | fetch | JavaScript fetches and inline script checks unless more specific script directives apply. |
script-src-elem | fetch | <script src> and script element bodies. |
script-src-attr | inline | Inline event-handler attributes such as onclick. |
style-src | fetch | Stylesheet fetches and inline style checks unless more specific style directives apply. |
style-src-elem | fetch | <link rel="stylesheet"> and <style> elements. |
style-src-attr | inline | Inline style="" attributes. |
img-src | fetch | <img>, background-image, favicons. |
connect-src | fetch | fetch(), XHR, WebSocket, EventSource, beacon. |
font-src | fetch | @font-face sources. |
frame-src | fetch | <iframe> and <frame> documents. |
media-src | fetch | <audio>, <video>, <track>. |
object-src | fetch | <object>, <embed>, <applet>. Recommended: 'none'. |
worker-src | fetch | Dedicated Workers, Shared Workers, and Service Workers. |
child-src | fetch | Legacy fallback for workers and frames when worker-src / frame-src are absent. |
manifest-src | fetch | Web app manifest. |
frame-ancestors | navigation | Which parents may embed the page. Modern replacement for X-Frame-Options. |
form-action | navigation | Form submission targets. |
base-uri | document | Allowed <base> targets — blocks base-element injection. |
report-uri / report-to | reporting | Where the browser POSTs violation reports. |
require-trusted-types-for | document | Enforce Trusted Types for sinks ('script'). |
trusted-types | document | Allowed Trusted Type policy names. |
upgrade-insecure-requests | document | Rewrite http: sub-resource URLs to https:. Boolean directive. |
block-all-mixed-content | document | Block all mixed-content fetches. Boolean directive. Deprecated in favour of upgrade-insecure-requests. |
Source list grammar (CSP Level 3 §2.3.1)
Most fetch directives accept either the exact keyword 'none' or a whitespace-separated source
list. Every source expression is one of:
'self','none','unsafe-inline','unsafe-eval','unsafe-hashes','strict-dynamic','wasm-unsafe-eval','trusted-types-eval','report-sample'— keyword tokens, always single-quoted.'nonce-{base64}'— matches a specific inline script/style tag carrying the same nonce.'sha256-{base64}','sha384-...','sha512-...'— pre-computed hash of the inline content.https:,http:,data:,blob:,filesystem:,mediastream:— bare scheme tokens.https://*.example.com,https://cdn.example.com:8443/path,*.example.org— host-source patterns.*as a leading subdomain is allowed.
'none' is only meaningful by itself; if it appears beside another source expression, browsers
ignore it for that directive. Internationalized domain names must be punycode-encoded in host-source tokens.
Dangerous keywords — what they enable and why they're risky
'unsafe-inline'inscript-srcpermits inline<script>blocks andonclick-style event handlers. If an attacker can inject HTML, this often turns markup injection into script execution. Use nonces, hashes, orscript-src-attr 'none'instead. Instyle-srcthe impact is smaller, but CSS injection can still leak data, hide controls, or load attacker-controlled URLs.'unsafe-eval'inscript-srcpermitseval(),new Function(...), andsetTimeout(string, ...). Many template engines and older AngularJS bundles need it; modern code should not.'strict-dynamic'tells the browser to trust scripts spawned by an already-trusted script (one with a matching nonce/hash) and to ignore host-source allow-lists inscript-src. It is powerful, but if you forget the nonce/hash the policy blocks every parser-inserted script. Keep host sources only as a deliberate fallback for older browsers.- Wildcard
*in a directive defeats the purpose of CSP. Combined with'self'in the same directive, the'self'is redundant. data:inscript-srclets attackers smuggle scripts as data URIs.data:inimg-srcis common for inline icons and generated previews, but it is a high-risk choice for script, worker, object, or frame directives.
Nonces and hashes (the modern inline-script story)
Inline scripts are unavoidable in some stacks (Symfony Twig, server-rendered config blobs). Instead of
'unsafe-inline', use one of two mechanisms:
- Per-request nonce — the server generates a cryptographically random base64 string
per response, emits it in the header
(
script-src 'nonce-abc123==' 'strict-dynamic') and stamps each allowed inline tag withnonce="abc123==". The nonce changes on every request, so an attacker who can inject HTML cannot reuse a captured nonce. Do not reuse nonces across responses or expose them to untrusted template fragments. Symfony exposescsp_nonce()in Twig. - Static hash — pre-compute
SHA-256/384/512of the inline script body and list it as'sha256-base64Hash'. Useful for fully static pages. The hash covers the exact script or style bytes, so whitespace changes require regenerating the header. Event-handler attributes need'unsafe-hashes'in addition to a matching hash.
'strict-dynamic' + a nonce is the recommended modern pattern: trusted scripts can pull in
their own dependencies without having to enumerate every CDN host, while older browsers can still use the
explicit host sources you leave in script-src.
Recommended baseline for a static-but-SPA site
default-src 'self';
script-src 'self' 'nonce-{NONCE}' 'strict-dynamic';
script-src-attr 'none';
style-src 'self' 'nonce-{NONCE}';
style-src-attr 'none';
img-src 'self' data:;
font-src 'self';
connect-src 'self';
worker-src 'self';
manifest-src 'self';
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
upgrade-insecure-requests;
report-uri https://reports.example.com/csp;
report-to default;
The {NONCE} placeholder is replaced per response. 'strict-dynamic' lets the
already-trusted bundle pull in chunks without listing every CDN. script-src-attr 'none' and
style-src-attr 'none' close common inline-attribute gaps, while
object-src 'none' and frame-ancestors 'none' block plugin/embed and clickjacking
vectors. Only include report-to default when the response also sends a matching
Reporting-Endpoints header.
HTTP header vs meta tag
Prefer the Content-Security-Policy HTTP response header for production. A
<meta http-equiv="Content-Security-Policy"> tag can be useful for static hosting or a
quick local experiment, but it is parsed only after the browser reaches the tag and cannot fully replace a
response header.
frame-ancestorsis ignored in meta-delivered policies, so clickjacking protection needs an HTTP header.sandboxis ignored in meta-delivered policies and in report-only mode.Content-Security-Policy-Report-Onlyis an HTTP header, not a meta tag; use it to collect reports before enforcing a policy.- Resources fetched before the meta tag is parsed are not protected by that tag. Put CSP in headers when you control the server.
Reporting
Content-Security-Policy-Report-Only— same syntax, but the browser only reports violations rather than blocking. Use during rollout to surface false positives without breaking the site.report-uri https://...— deprecated but still useful for backwards compatibility. Ifreport-tois present, browsers that support it use the reporting group and ignorereport-uri.report-to group-name+ aReporting-Endpointsresponse header. This is the newer Reporting API path; keepreport-urialongside it until your target browsers and report collector support the newer report format.
Use cases
- Author a new policy — start from a tight baseline (
default-src 'self') and add directives one at a time until the page loads. The build mode emits the header value, anhtmlMetaTagform, and a warnings panel. - Audit an existing header — paste a header captured from
curl -Ior DevTools and the parser surfaces what the browser will actually do, plus analysis warnings. - CI lint — call the API endpoint from a pipeline and fail the build if a high-severity
warning appears (e.g.,
'unsafe-inline'introduced inscript-src). - Migration from
X-Frame-Options— confirm a newframe-ancestorsdirective covers the same cases as the legacy header. - Trusted Types rollout — verify the
require-trusted-types-for 'script'+trusted-typespair are spelled correctly before flipping enforcement.
Security rating
- Status — CSP Level 3 is a W3C Working Draft on the Recommendation track. Core CSP is broadly implemented in modern browsers, but newer directives and reporting behavior still need target-browser testing.
- Strength — A well-crafted CSP is a strong last line of defense against XSS and content
injection. A poorly-crafted CSP with wildcards,
'unsafe-inline', or missing fallbacks can provide little practical protection. - Recommended usage — every production web application. Roll out in report-only mode first; promote to enforcing once reports are clean.
- Known weaknesses — CSP cannot fix unsafe server-side rendering, vulnerable
dependencies, JSONP-style endpoints, or DOM XSS sinks by itself.
http:origins inscript-srcremain vulnerable to active man-in-the-middle injection. - Industry guidance — W3C CSP Level 3, OWASP's CSP Cheat Sheet, Google's strict CSP guidance, and MDN's browser-focused CSP guide.
References
- W3C CSP Level 3 — the source of truth for directives, source-list grammar, and analysis rules.
- W3C Trusted Types
— the CSP-integrated sink-hardening model behind
require-trusted-types-forandtrusted-types. - W3C Reporting API
— the model for named reporting endpoints used by
report-to. - MDN — Content Security Policy — the most readable reference with examples.
- OWASP CSP Cheat Sheet — pragmatic guidance and common pitfalls.
- web.dev — A strict CSP
— Google's recommended modern hash/nonce +
'strict-dynamic'pattern.
API Usage Example:
POST /api/tools/security/csp-generator
Content-Type: application/json
{
"operation": "build",
"policy": {
"default-src": [
"'self'"
],
"script-src": [
"'self'",
"'nonce-{NONCE}'"
]
}
}