// free tool

Content Security Policy (CSP) Generator

Build a Content Security Policy directive by directive, with each choice explained as you make it.

Runs entirely in your browser. Nothing you paste is uploaded, logged, or stored.

default-srcFallback for every fetch directive you leave unset.
script-srcWhere JavaScript is allowed to load and run from.
style-srcWhere stylesheets and inline <style> are allowed from.
img-srcWhere images can load from.
font-srcWhere web fonts can load from.
connect-srcWhere fetch, XHR, WebSocket and EventSource can connect to.
frame-srcWhich origins can be embedded in an <iframe> on this page.
frame-ancestorsWhich origins are allowed to embed this page (clickjacking control).
form-actionWhere <form> elements on this page can submit to.
base-uriWhat a <base href> on the page is allowed to be set to.
object-srcWhere legacy <object>/<embed>/<applet> plugin content can load from.
report-uriOptional. Where violation reports are sent (header only — ignored in the meta tag).

HTTP header

Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; object-src 'none';

<meta> tag

<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; form-action 'self'; base-uri 'self'; object-src 'none';">

frame-ancestors, report-uri and report-to are dropped from the meta tag because browsers ignore them there.

How to use this CSP generator

Work through the directives one at a time. For each, pick 'none' to block that resource type entirely, 'self' to allow only your own origin, or add specific origins in the text field — space- or comma-separated, so https://cdn.example.com https://fonts.googleapis.com is valid. The header at the bottom updates as you go, and any risky combination gets an inline warning right under the directive that caused it, so you see the trade-off the moment you make it rather than after shipping it.

Report-only first, then enforce

The single biggest mistake teams make with CSP is writing a policy from scratch and shipping it as an enforcing header on day one. Something always breaks — an analytics snippet, a font CDN, a widget you forgot about — and it breaks silently in production rather than showing up in a code review. The fix is built into the spec: Content-Security-Policy-Report-Only behaves exactly like Content-Security-Policy except that it never blocks anything. It only reports what would have been blocked, to whatever endpoint you set in report-uri or report-to.

Run report-only for long enough to see real traffic patterns — a few days for a high-traffic site, longer if traffic is light or usage is seasonal. Read the reports, add the legitimate origins you missed, and ignore the noise every CSP report endpoint gets from browser extensions and ad-blockers rewriting pages in ways your policy never anticipated. When the reports stop surfacing anything you need to fix, rename the header from Content-Security-Policy-Report-Only to Content-Security-Policy and you're enforcing the same policy you already validated.

Handling inline scripts: nonces and hashes

The temptation once something breaks is to add 'unsafe-inline' to script-src and move on — and that one checkbox undoes most of what the policy was for. CSP gives you two better options for legitimately allowing specific inline scripts. A nonce is a random, base64-encoded value your server generates fresh on every response and includes both in the header and as a nonce attribute on the script tags you trust:

Content-Security-Policy: script-src 'self' 'nonce-2726c7f26c';

<script nonce="2726c7f26c">
  // this runs — the nonce matches
</script>

A hash source works when the inline script's content never changes — you compute a SHA-256/384/512 hash of the exact script text (including whitespace) and list it in the policy. Any script whose content doesn't match a listed hash is blocked, nonce or not. Hashes suit a handful of static inline scripts; nonces suit server-rendered pages where the trusted script set is generated per request. Either approach lets you keep script-src free of 'unsafe-inline' while still allowing the inline code you actually wrote.

Why some checkboxes aren't offered everywhere

You'll notice 'unsafe-inline' and data: are only offered on default-src, script-src and style-src — they're the directives those keywords are actually meaningful for. base-uri and object-src only offer 'self' and custom origins, because in practice the only two sane values for either are "my own origin" and 'none' — anything else is an unusual, deliberate choice you should type in yourself.

Header vs. meta tag

The generator builds both, but they are not interchangeable. A <meta http-equiv="Content-Security-Policy"> tag cannot set frame-ancestors, report-uri, report-to or sandbox — the spec disallows them there and browsers drop them without warning, so the generator omits them from the meta output entirely rather than showing you a tag that silently does less than it looks like it does. Report-only mode has no meta equivalent at all; it only works as an HTTP header. If you control your server configuration, ship the header.

Once your policy is live, run it through the CSP checker to confirm it evaluates the way you expect, or check it alongside the rest of your response headers with the security headers checker.

Frequently asked questions

What does this generator actually build?

A Content-Security-Policy header value (and the equivalent <meta> tag) assembled from the directives you select. Pick a source type — 'self', specific origins, data:, https:, or 'unsafe-inline' — for each directive, and the header updates live as you go.

Should I ship the header or the <meta> tag?

The header, if you can set one — it's the only delivery method that supports frame-ancestors, report-uri and report-to, all of which browsers silently ignore in a <meta> tag. Use the meta tag only when you genuinely can't touch server response headers, such as on some static hosts.

Which preset should I start with?

Strict if you're building the policy alongside a new site or app and can fix violations as they come up. Balanced if you're retrofitting CSP onto something that already exists and don't yet know what it needs. Report-only trial if you want to observe real traffic before blocking anything.

What is the rollout path for an existing site?

Start in report-only mode with a reasonable first guess (the Balanced preset is a fair starting point), point report-uri at an endpoint you control, and watch what gets reported for a few days to a couple of weeks depending on traffic. Fix genuine gaps in the policy, ignore reports from browser extensions and bots, then switch the header from Content-Security-Policy-Report-Only to Content-Security-Policy once reports settle down.

Why does the generator warn me about unsafe-inline instead of just not offering it?

Because sometimes it's the honest answer — plenty of real sites ship inline styles from a UI library and accept the (low) risk. The warning is there so that choice is made knowingly rather than by default, especially for script-src, where the same checkbox is a much bigger trade-off.

Is anything I select here sent anywhere?

No. The whole tool runs in your browser — there is no server request involved in building the policy. Nothing you configure is uploaded, logged, or stored.

Is this CSP generator free?

Yes, completely free with no sign-up, and no limit on how many policies you build.

// one check is not a security programme

This checks one thing. Averto checks everything.

A csp generator tells you about a single slice of your attack surface. Averto scans your websites, web apps, code, dependencies, containers, configuration and secrets in one place, then explains every finding in plain English.