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, 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- 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 |
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 all sessions |
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
--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
--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 tools for starting sessions, crawling URLs, generating policies, exporting in various formats, diffing sessions, and scoring policies.
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-elem 'sha256-runtimeInjectedStyleHash=' \
--extra-script-elem 'sha256-runtimeInjectedScriptHash='HTTP 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