Content Security Policy Builder Tool - Build a CSP Header and Lint Weak Settings

First Published:
Last Updated:

Build a Content-Security-Policy from directives and sources, then copy it as an HTTP response header or a <meta> tag - or switch to the Linter to paste an existing policy and flag syntax errors and weak settings ('unsafe-inline', 'unsafe-eval', wildcards, missing object-src / frame-ancestors, and more). All processing is performed entirely in your browser - your data never leaves your device.

⚠️ IMPORTANT DISCLAIMER:

  • This tool is provided "AS IS" without any warranties of any kind.
  • It builds and checks policy text only. It never applies a CSP to a real site, never sends a request, and never fetches any URL.
  • Warnings are best-effort guidance, not a security audit. A policy with no warnings is not guaranteed to be safe.
  • Browser support and the specification evolve; always confirm against the official sources and your own testing.
  • By using this tool, you accept full responsibility for any outcomes.

This tool uses client-side JavaScript for all processing. No data is transmitted to servers, no files are uploaded online, all processing happens locally in your browser. Once loaded, this tool continues to work even without an internet connection. For more details, please refer to our Web Tools Disclaimer.

Build a Policy

Tick the keyword sources you want for each directive and add hosts, schemes, nonces, or hashes as free text. The policy below updates as you type, with inline guidance from the same rules the Linter uses.

Reporting and advanced directives

Space-separated policy names; add 'none' to disallow creating policies.

Has no effect when delivered via a <meta> tag.

Names a group declared in a separate Reporting-Endpoints response header.

Deprecated, but still useful for older browsers alongside report-to.

Generated Policy

About This Tool

A Content Security Policy (CSP) is an HTTP response header (or <meta> tag) that tells the browser which sources of script, style, images, and other resources a page is allowed to load - a primary defense against cross-site scripting (XSS) and a control for clickjacking and other injection attacks. Writing one by hand is error-prone: the directive names, the quoting rules for keywords like 'self' and 'unsafe-inline', and the subtle interactions between 'strict-dynamic', nonces, and host allowlists are easy to get wrong. This tool helps on both sides, entirely in your browser:

  • Builder: assemble a policy directive by directive and copy it as an HTTP header, a policy value, or a <meta> tag - with Content-Security-Policy and Content-Security-Policy-Report-Only both supported.
  • Linter: paste an existing policy to get line-by-line Error / Warning / Info results, each labeled as derived from the specification or as this tool's recommendation.

Directive names, source keywords, and deprecation status were confirmed against the official documentation as of 2026-06-23. The specification and browser support evolve; re-check the sources below for the current set.

Specification Sources

Directive Reference

The directives this tool understands, by category, confirmed against MDN as of 2026-06-23. Deprecated and experimental directives are built only so the Linter can flag them.

DirectiveCategoryPurposeStatus
default-srcFetchFallback for the other fetch directives
script-srcFetchJavaScript and WebAssembly sources
script-src-elem / script-src-attrFetchSources for <script> elements / inline event handlers
style-srcFetchStylesheet sources
style-src-elem / style-src-attrFetchSources for style elements / inline style attributes
img-srcFetchImage and favicon sources
connect-srcFetchfetch / XHR / WebSocket / EventSource targets
font-srcFetchFont sources (@font-face)
media-srcFetch<audio> / <video> / <track> sources
object-srcFetch<object> / <embed> sources (best set to 'none')
frame-src / child-src / worker-srcFetchFrame, nested context, and worker sources
manifest-src / fenced-frame-srcFetchManifest and <fencedframe> sources
prefetch-srcFetchPrefetch / prerender sourcesExperimental
base-uriDocumentAllowed URLs for the <base> element
sandboxDocumentApplies an iframe-style sandboxNo effect via <meta>
form-actionNavigationAllowed form submission targets
frame-ancestorsNavigationAllowed embedding parents (anti-clickjacking)No effect via <meta>
require-trusted-types-for / trusted-typesOtherEnforce and allowlist Trusted Types
upgrade-insecure-requestsOtherTreat HTTP URLs as HTTPS
report-toReportingViolation reporting endpoint groupNo effect via <meta>
report-uriReportingLegacy violation report URLDeprecated
block-all-mixed-contentOtherBlocks mixed contentDeprecated

Source Keyword Reference

Keyword sources must be wrapped in single quotes. Nonces and hashes are also quoted. Host sources (example.com, *.example.com) and scheme sources (https:, data:, blob:) are written without quotes.

KeywordMeaning
'self'Same-origin resources
'none'Blocks everything for that directive (must appear alone)
'unsafe-inline'Allows inline scripts/styles (weakens XSS protection)
'unsafe-eval'Allows eval() and similar APIs
'unsafe-hashes'Allows specific inline event handlers / styles by hash
'strict-dynamic'Lets a nonce/hash-trusted script load further scripts; host allowlists are then ignored
'wasm-unsafe-eval'Allows WebAssembly compilation without 'unsafe-eval'
'report-sample'Includes a sample of the offending code in violation reports
'inline-speculation-rules'Allows inline speculation rules scripts
'nonce-<base64>'Allows an element carrying the matching, per-response random nonce
'sha256-<base64>'Allows an inline element whose content matches the hash (also sha384 / sha512)
https: / data: / blob:Scheme sources
*Any source - the broadest, least safe allowlist

Linter Rules

Each check is labeled spec (defined or required by the specification) or recommendation (a hardening suggestion). No rule here invents a requirement the specification does not state.

IDLevelOriginWhat it checks
E1Errorspec'none' combined with other sources in the same directive
E2ErrorspecKeyword, nonce, or hash missing the required single quotes
E3ErrorspecEmpty or malformed directive name
W1Warningspec'unsafe-inline' in script-src / style-src / default-src
W2Warningspec'unsafe-eval' present
W3WarningrecommendationA bare * wildcard source
W4WarningrecommendationNo default-src fallback
W5Warningrecommendationobject-src not locked to 'none'
W6WarningrecommendationNo base-uri (base-tag injection)
W7WarningrecommendationNo frame-ancestors (clickjacking)
W8WarningspecDuplicate directive (later occurrence ignored)
W9WarningspecDeprecated directive (block-all-mixed-content, report-uri)
W10Warningrecommendationdata: in a script directive (XSS vector)
I1Infospec'unsafe-inline' ignored when a nonce/hash is present
I2Infospec'strict-dynamic' makes host/scheme allowlists ignored
I3Inforecommendationreport-uri / report-to declared without the other
I4InfospecDirective has no effect when delivered via <meta>
I5InforecommendationUnknown or removed directive name
I6InforecommendationNo reporting directive configured

How to Use

  1. Builder tab: for each directive, tick the keyword sources and type any hosts, schemes, nonces, or hashes. Add more directives from the picker, set advanced and reporting directives, and toggle Report-Only if you are still testing.
  2. Copy the HTTP header, the policy value, or the <meta> tag. Watch the inline review for weak settings as you build.
  3. Linter tab: paste an existing policy (or load an example) and click "Check" (or press Ctrl+Enter / Cmd+Enter) for line-by-line Error / Warning / Info results.
  4. Copy Report to take the findings into a pull request or review checklist.

Features:

  • 🛠️ Directive Builder: Data-driven directive rows that offer only the keywords valid for each directive, plus host / scheme / nonce / hash entry
  • 📄 Three Output Forms: HTTP header, policy value, and <meta> tag, with Content-Security-Policy and -Report-Only both supported
  • 🔍 Linter: Tokenizes a pasted policy and reports Error / Warning / Info, each labeled spec or recommendation
  • 🏷️ Spec vs. Recommendation: Every finding states whether it comes from the specification or is a hardening suggestion - no invented rules
  • 📋 Examples and Copy Report: Strict, moderate, and common-loose presets plus a copyable text report
  • 🔒 Privacy First: All processing happens locally - no data sent to servers, no request is made, no URL is fetched
  • ⌨️ Keyboard Shortcut: Ctrl+Enter (Cmd+Enter) runs the Linter

FAQ

What is the difference between 'self' and 'none'?

'self' allows resources from the page's own origin (same scheme, host, and port). 'none' blocks every source for that directive and must appear on its own - combining it with any other source is a syntax error. Use 'none' for directives you want fully locked down, such as object-src 'none'.

Is 'unsafe-inline' safe to use?

No - it is named "unsafe" for a reason. It allows inline <script> and event handlers, which is one of the most common XSS vectors and defeats much of the point of a CSP. Prefer a per-response 'nonce-...' or a content 'sha256-...' hash. Note that when a nonce or hash is present, browsers that support them ignore 'unsafe-inline', so it can remain only as a fallback for very old browsers.

Should I use the HTTP header or the <meta> tag?

The HTTP response header is the recommended, fully featured delivery method. A <meta> tag is handy when you cannot set headers, but several directives - frame-ancestors, sandbox, report-uri, and report-to - have no effect in a <meta> tag, and Content-Security-Policy-Report-Only cannot be delivered that way at all. This tool flags those cases.

What does 'strict-dynamic' do?

It tells the browser to trust scripts that already carry a valid nonce or hash to load further scripts, without those additional scripts needing their own nonce or hash. In supporting browsers it also causes host and scheme allowlist entries in that directive to be ignored, so trust flows through nonces/hashes rather than URL allowlists - a more robust pattern for modern apps with third-party scripts.

What is the difference between enforce and Report-Only?

Content-Security-Policy enforces the policy: violating resources are blocked. Content-Security-Policy-Report-Only blocks nothing - it only reports what would have been blocked, which lets you test a policy safely before enforcing it. You can even send both headers at once: one enforced and one stricter policy in Report-Only to measure the next tightening.

Important Notes

  • CSP directives and keywords evolve. This builder follows the specification as of 2026-06-23. Warnings are best-effort guidance, not a security audit - a policy without warnings is not guaranteed to be safe. Always test in Report-Only mode before enforcing.
  • The Linter checks syntax and known weak settings. It cannot know your application's real resource needs, cannot confirm that a nonce is actually random and per-response, and cannot verify that a host you allowlist is itself trustworthy.
  • Every finding is a flag for review, not a verdict. A clean result means none of this tool's checks matched - treat it as one input to a manual review, not a safety certificate.
  • Browser support for individual directives and keywords differs. Confirm behavior against the official sources above and your own testing across the browsers you target.
  • This tool never applies a policy to a real site, never sends a request, and never fetches any URL. All processing happens locally in your browser.

Related Tools

Related Articles


References:
Tech Blog with curated related content
Web Tools Collection

Written by Hidekazu Konishi