Automatically generate production-ready Content Security Policy headers by crawling your website. CSP Analyser headlessly browses a target site with a deny-all report-only CSP, captures every violation, and produces a minimal, correct policy you can deploy immediately.
Available as a CLI and as an MCP server for AI coding agents (Claude Code, Cursor, Windsurf, Copilot).
- Headless crawling with configurable depth and page limits
- Interactive mode for manual browsing with live violation capture
- Authentication support (storage state with sessionStorage capture, manual login, raw cookies)
- Dual violation capture (DOM events + HTTP reporting endpoint)
- Smart policy optimization (common sources factored into
default-src) - Nonce generation replacing
unsafe-inlinewithnonce-placeholders - Full inline content hash extraction (scripts, styles, event handlers, style attributes)
- Hash-based
unsafe-inlineremoval using SHA-256/384/512 hashes unsafe-evalstripping for iterative hardeningstrict-dynamicsupport for script loading- Auto-collapse excessive hashes to
unsafe-inline(configurable threshold) - Static site mode: detects static hosting and disables nonce suggestions
- Static React/Expo profile: keeps scripts hash-strict while allowing scoped
style-src-attrfallback for hash-heavy static exports - Hash stability analysis: warns when hashes are build-specific and impractical
unsafe-evalsource attribution: identifies which dependencies requireeval()- Session diffing to compare policy changes over time
- Policy scoring and security grading
- Permissions-Policy header capture
- Export to 9 formats: HTTP header,
<meta>tag, nginx, Apache, Cloudflare Workers, Cloudflare Pages, Azure Front Door (Bicep), Helmet.js, JSON - Browserless static-site mode (
hash-static): scan built HTML files on disk and inject the policy directly — no Playwright, CI-friendly
npm install -g @makerx/csp-analyserThen install the browser dependency:
csp-analyser setupRequires Node.js 20+.
Crawl a public site and generate a CSP header:
csp-analyser crawl https://example.comCrawl with authentication (Playwright storage state):
csp-analyser crawl https://example.com --storage-state auth.jsonInteractive mode for sites that need manual navigation:
csp-analyser interactive https://example.comSave your auth session for later headless crawls:
csp-analyser interactive https://example.com --save-storage-state auth.jsonHave a static-site build on disk? Generate the policy from HTML files without launching a browser:
npm run build # your framework's build (VitePress, Next.js static export, Astro, etc.)
csp-analyser hash-static dist/ --inject # hashes inline content and writes <meta> into every <head>| Command | Description |
|---|---|
crawl <url> |
Headless crawl and generate policy |
interactive <url> |
Manual browsing with violation capture |
audit <url> |
Audit an existing CSP deployment and generate updated policy |
hash-static <path>... |
Hash inline content in built HTML files, no browser required |
generate <session-id> |
Regenerate policy from a previous session |
export <session-id> |
Export policy in a specific format |
diff <id1> <id2> |
Compare policies between two sessions |
score <session-id> |
Score a generated policy |
permissions <session-id> |
Show captured Permissions-Policy headers |
sessions |
List sessions for the current project |
setup |
Install browser and check dependencies |
start |
Run the MCP server over stdio (for AI agents) |
--depth <n> Crawl depth (default: 1)
--max-pages <n> Maximum pages to visit (default: 10)
--strictness <level> strict | moderate | permissive (default: moderate)
--format <fmt> header | meta | nginx | apache | cloudflare |
cloudflare-pages | azure-frontdoor | helmet | json
--nonce Replace unsafe-inline with nonce placeholders
--strict-dynamic Add strict-dynamic alongside nonces (implies --nonce)
--hash Remove unsafe-inline when hash sources are available
--strip-unsafe-eval Remove unsafe-eval from the generated policy
--collapse-hash-threshold <n> Collapse hashes to 'unsafe-inline' when count
exceeds <n> per directive
--static-site Target is a static site (disables nonce suggestions)
--static-profile <p> Static framework profile: react-expo
--storage-state <path> Playwright storage state file for auth
--cookies <json> Raw cookies as JSON string
--manual-login Open browser for manual login before crawl
--report-only Generate report-only header
--project <name> Override auto-detected project name
--all Show sessions from all projects (sessions command)
--no-color Disable colored output
CSP Analyser exposes an MCP server for AI coding agents over stdio:
csp-analyser startAdd to your MCP client config (e.g. Claude Code mcp.json):
{
"mcpServers": {
"csp-analyser": {
"command": "csp-analyser",
"args": ["start"]
}
}
}The MCP server provides 12 tools for starting sessions, crawling URLs, hashing static HTML builds, generating policies, exporting in various formats, diffing sessions, scoring policies, inspecting sessions, listing sessions, querying violations, reading Permissions-Policy headers, and auditing existing CSP deployments.
For statically-built sites where all inline content is emitted at build time, hash-static avoids the Playwright crawl entirely. It scans HTML files on disk, hashes every inline <script>, <style>, style="" attribute, and on*="" event handler (including empty-string values, which browsers still evaluate against CSP), and either emits the policy or writes it directly into each <head> as a <meta> tag.
csp-analyser hash-static docs/.vitepress/dist --injectTypical package.json usage:
{
"scripts": {
"build": "vitepress build docs && csp-analyser hash-static docs/.vitepress/dist --inject"
}
}For content that framework JS injects at runtime (not present in the built HTML), capture those hashes once via crawl and feed them back:
csp-analyser hash-static dist/ --inject \
--extra "style-src-elem='sha256-runtimeInjectedStyleHash='" \
--extra "script-src-elem='sha256-runtimeInjectedScriptHash='"Or export a crawl as JSON and merge the whole policy at once:
csp-analyser export --format json > crawl-policy.json
csp-analyser hash-static dist/ --inject --merge-json crawl-policy.jsonHTTP header:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com
nginx:
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com" always;Apache:
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com"Cloudflare Workers, Cloudflare Pages, Azure Front Door (Bicep), Helmet.js, <meta> tag, JSON are also supported. See the docs for examples.
Full documentation is available at cspanalyser.com.
npm install
npx playwright install chromium
npm run build
npm run testMIT