🛡️ CSP Generator

🔧 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

{{ entry.name }} {{ entry.tokens.join(' ') }}

📤 Analysis

No warnings — looks healthy.

Found {{ currentWarnings.length }} item(s).

⚠️ Warnings

{{ warn.severity }} {{ warn.directive }}
{{ warn.message }}
Fix: {{ warn.recommendation }}
⚠️

ℹ️ 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-srcfallbackDefault when a more specific fetch directive is not set.
script-srcfetchJavaScript fetches and inline script checks unless more specific script directives apply.
script-src-elemfetch<script src> and script element bodies.
script-src-attrinlineInline event-handler attributes such as onclick.
style-srcfetchStylesheet fetches and inline style checks unless more specific style directives apply.
style-src-elemfetch<link rel="stylesheet"> and <style> elements.
style-src-attrinlineInline style="" attributes.
img-srcfetch<img>, background-image, favicons.
connect-srcfetchfetch(), XHR, WebSocket, EventSource, beacon.
font-srcfetch@font-face sources.
frame-srcfetch<iframe> and <frame> documents.
media-srcfetch<audio>, <video>, <track>.
object-srcfetch<object>, <embed>, <applet>. Recommended: 'none'.
worker-srcfetchDedicated Workers, Shared Workers, and Service Workers.
child-srcfetchLegacy fallback for workers and frames when worker-src / frame-src are absent.
manifest-srcfetchWeb app manifest.
frame-ancestorsnavigationWhich parents may embed the page. Modern replacement for X-Frame-Options.
form-actionnavigationForm submission targets.
base-uridocumentAllowed <base> targets — blocks base-element injection.
report-uri / report-toreportingWhere the browser POSTs violation reports.
require-trusted-types-fordocumentEnforce Trusted Types for sinks ('script').
trusted-typesdocumentAllowed Trusted Type policy names.
upgrade-insecure-requestsdocumentRewrite http: sub-resource URLs to https:. Boolean directive.
block-all-mixed-contentdocumentBlock 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' in script-src permits inline <script> blocks and onclick-style event handlers. If an attacker can inject HTML, this often turns markup injection into script execution. Use nonces, hashes, or script-src-attr 'none' instead. In style-src the impact is smaller, but CSS injection can still leak data, hide controls, or load attacker-controlled URLs.
  • 'unsafe-eval' in script-src permits eval(), new Function(...), and setTimeout(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 in script-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: in script-src lets attackers smuggle scripts as data URIs. data: in img-src is 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:

  1. 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 with nonce="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 exposes csp_nonce() in Twig.
  2. Static hash — pre-compute SHA-256/384/512 of 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-ancestors is ignored in meta-delivered policies, so clickjacking protection needs an HTTP header.
  • sandbox is ignored in meta-delivered policies and in report-only mode.
  • Content-Security-Policy-Report-Only is 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. If report-to is present, browsers that support it use the reporting group and ignore report-uri.
  • report-to group-name + a Reporting-Endpoints response header. This is the newer Reporting API path; keep report-uri alongside 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, an htmlMetaTag form, and a warnings panel.
  • Audit an existing header — paste a header captured from curl -I or 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 in script-src).
  • Migration from X-Frame-Options — confirm a new frame-ancestors directive covers the same cases as the legacy header.
  • Trusted Types rollout — verify the require-trusted-types-for 'script' + trusted-types pair 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 in script-src remain 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

API Usage Example:

POST /api/tools/security/csp-generator
Content-Type: application/json

{
    "operation": "build",
    "policy": {
        "default-src": [
            "'self'"
        ],
        "script-src": [
            "'self'",
            "'nonce-{NONCE}'"
        ]
    }
}
Ready