155 lines
8 KiB
HTML
155 lines
8 KiB
HTML
---
|
||
title: "cspresso Docs"
|
||
description: "Docs for cspresso: crawl a site with headless Chromium and generate a draft Content-Security-Policy; evaluate candidates in Report-Only mode."
|
||
---
|
||
<main class="py-5">
|
||
<div class="container">
|
||
<div class="row g-4">
|
||
<div class="col-lg-3">
|
||
<div class="sticky-lg-top" style="top: 90px;">
|
||
<div class="fw-semibold mb-2">On this page</div>
|
||
<div class="list-group small">
|
||
<a class="list-group-item list-group-item-action" href="#install">Install</a>
|
||
<a class="list-group-item list-group-item-action" href="#run">Run</a>
|
||
<a class="list-group-item list-group-item-action" href="#output">Output</a>
|
||
<a class="list-group-item list-group-item-action" href="#inline">Inline scripts & styles</a>
|
||
<a class="list-group-item list-group-item-action" href="#evaluate">Evaluate (Report-Only)</a>
|
||
<a class="list-group-item list-group-item-action" href="#flags">Flags</a>
|
||
</div>
|
||
|
||
<div class="mt-3 small text-secondary">
|
||
Prefer canonical docs? See the <a class="link-secondary" href="https://git.mig5.net/mig5/cspresso#readme" target="_blank" rel="noreferrer">README</a>.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-lg-9">
|
||
<header class="mb-4">
|
||
<div class="kicker mb-2"><i class="bi bi-journal-text"></i> Docs</div>
|
||
<h1 class="display-6 fw-800 mb-2">Usage</h1>
|
||
<p class="text-secondary mb-0">
|
||
cspresso crawls up to <code>--max-pages</code> same-origin pages in Chromium, observes what loads, and emits a draft CSP.
|
||
</p>
|
||
</header>
|
||
|
||
<section id="install" class="mb-5">
|
||
<h2 class="section-title fw-bold">Install</h2>
|
||
<div class="row g-3">
|
||
<div class="col-lg-7">
|
||
<div class="codeblock">
|
||
<button class="btn btn-sm btn-outline-secondary copy-btn" data-copy-target="#docinst"><i class="bi bi-clipboard"></i> Copy</button>
|
||
<pre class="terminal mb-0"><code id="docinst"># Recommended
|
||
pipx install cspresso
|
||
|
||
# Or plain pip (use a venv)
|
||
pip install cspresso
|
||
|
||
# An AppImage is also available on the
|
||
# git repo Releases page.
|
||
</code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-5">
|
||
<div class="callout p-4 h-100">
|
||
<div class="fw-semibold mb-2">Python + Playwright</div>
|
||
<div class="text-muted">
|
||
You need Python 3.10+ and Playwright’s Chromium. cspresso can auto-install Chromium if missing.
|
||
</div>
|
||
<hr>
|
||
<div class="small text-secondary">
|
||
Verify Releases artifacts with the mig5 key:
|
||
<a class="link-secondary" href="https://mig5.net/static/mig5.asc" target="_blank" rel="noreferrer">https://mig5.net/static/mig5.asc</a>
|
||
(fingerprint <code>54A91143AE0AB4F7743B01FE888ED1B423A3BC99</code>).
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="run" class="mb-5">
|
||
<h2 class="section-title fw-bold">Run</h2>
|
||
<div class="codeblock">
|
||
<button class="btn btn-sm btn-outline-secondary copy-btn" data-copy-target="#docrun"><i class="bi bi-clipboard"></i> Copy</button>
|
||
<pre class="terminal mb-0"><code id="docrun">cspresso https://example.com --max-pages 10</code></pre>
|
||
</div>
|
||
<div class="mt-3 text-secondary">
|
||
The crawl stays on the same origin (it follows internal links) and will wait for <code>networkidle</code> plus a small “settle”
|
||
delay to catch late fetches.
|
||
</div>
|
||
</section>
|
||
|
||
<section id="output" class="mb-5">
|
||
<h2 class="section-title fw-bold">Output</h2>
|
||
<p class="text-secondary">
|
||
Default output prints visited URLs as comments and then the proposed header line.
|
||
Use <span class="chip">--json</span> for machine-readable output.
|
||
</p>
|
||
<div class="codeblock">
|
||
<button class="btn btn-sm btn-outline-secondary copy-btn" data-copy-target="#docjson"><i class="bi bi-clipboard"></i> Copy</button>
|
||
<pre class="terminal mb-0"><code id="docjson">cspresso https://example.com --json</code></pre>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="inline" class="mb-5">
|
||
<h2 class="section-title fw-bold">Inline scripts & styles</h2>
|
||
<div class="callout p-4">
|
||
<div class="fw-semibold mb-2">Why this is hard</div>
|
||
<div class="text-muted">
|
||
If the page uses nonces, you must generate a new nonce per HTML response and inject it into both the CSP header and the HTML tags.
|
||
Hashes only work when inline content is stable byte-for-byte. For <code>style="..."</code> and <code>on*</code> attributes,
|
||
browsers require <code>'unsafe-hashes'</code> for hashes to apply.<br/>Not to worry, cspresso will detect these and generate the hashes
|
||
in its response, offering them as <code>style-src-attr</code> options or with <code>unsafe-hashes</code> for older browsers.
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="evaluate" class="mb-5">
|
||
<h2 class="section-title fw-bold">Evaluate (Report-Only)</h2>
|
||
<p class="text-secondary">
|
||
Provide a CSP string to <span class="chip">--evaluate</span> and cspresso will inject it as
|
||
<code>Content-Security-Policy-Report-Only</code> on HTML responses during the crawl. If any violations are detected, it exits with code <code>1</code>.
|
||
</p>
|
||
<p class="text-secondary">This is a great way of testing a cspresso-brewed CSP before actually adding it to your site.</p>
|
||
|
||
<div class="codeblock">
|
||
<button class="btn btn-sm btn-outline-secondary copy-btn" data-copy-target="#doceval"><i class="bi bi-clipboard"></i> Copy</button>
|
||
<pre class="terminal mb-0"><code id="doceval">cspresso https://example.com \
|
||
--bypass-csp \
|
||
--evaluate "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net;" \
|
||
--json</code></pre>
|
||
</div>
|
||
|
||
<div class="mt-3 small text-secondary">
|
||
Recommendation: use <code>--bypass-csp</code> with <code>--evaluate</code> so existing CSP enforcement doesn’t change the page’s behaviour during testing.
|
||
</div>
|
||
</section>
|
||
|
||
<section id="flags">
|
||
<h2 class="section-title fw-bold">Flags</h2>
|
||
<p class="text-secondary">A condensed reference of the most-used options:</p>
|
||
|
||
<div class="row g-3">
|
||
<div class="col-md-6"><div class="callout p-4 h-100">
|
||
<div class="fw-semibold mb-2">Crawling</div>
|
||
<div class="text-muted"><span class="chip">--max-pages</span> <span class="chip">--timeout-ms</span> <span class="chip">--settle-ms</span> <span class="chip">--headed</span></div>
|
||
</div></div>
|
||
<div class="col-md-6"><div class="callout p-4 h-100">
|
||
<div class="fw-semibold mb-2">Policy shaping</div>
|
||
<div class="text-muted"><span class="chip">--include-sourcemaps</span> <span class="chip">--upgrade-insecure-requests</span> <span class="chip">--allow-blob</span> <span class="chip">--unsafe-eval</span></div>
|
||
</div></div>
|
||
<div class="col-md-6"><div class="callout p-4 h-100">
|
||
<div class="fw-semibold mb-2">Playwright</div>
|
||
<div class="text-muted"><span class="chip">--browsers-path</span> <span class="chip">--no-install</span> <span class="chip">--with-deps</span></div>
|
||
</div></div>
|
||
<div class="col-md-6"><div class="callout p-4 h-100">
|
||
<div class="fw-semibold mb-2">Evaluation</div>
|
||
<div class="text-muted"><span class="chip">--bypass-csp</span> <span class="chip">--evaluate</span> <span class="chip">--ignore-non-html</span> <span class="chip">--json</span></div>
|
||
</div></div>
|
||
</div>
|
||
|
||
</section>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|