## TL;DR
Start with default-src 'self', run it in report-only mode for a week, then enforce. Add only the sources your app actually needs: your CDN, your analytics, your fonts. A minimal CSP you enforce beats a perfect CSP you never ship.

```text
Content-Security-Policy header: minimal working setup
```

### Use this when
- Adding a Content-Security-Policy to a site for the first time
- A security scan flags a missing or weak CSP
- Your current CSP is default-src * and you want a real one
- You broke the site with an over-strict CSP and need to start over

### Not for
- Nonce or hash-based CSP for apps with heavy inline scripts (advanced setup)
- The complete CSP directive reference (this is the minimal working version)
- CSP for browser extensions or Electron apps

### Steps

**1. Start with the minimal policy.**

default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'. This blocks everything except resources from your own origin, kills plugins and object tags, and prevents framing.

Expected: a four-directive policy you can explain in one breath.

**2. Deploy it in report-only mode first.**

Send it as Content-Security-Policy-Report-Only with a report-uri or report-to endpoint. Watch the violation reports for a few days to a week to learn what your app actually loads.

Expected: a list of real resource sources your app needs, from the reports.

**3. Allowlist only what the reports show you need.**

Common additions: script-src for your CDN and analytics domains, style-src for your font or CSS CDN, img-src for image hosts, connect-src for your API domains. Add each source you saw in the reports, nothing speculative.

Expected: a policy that covers every legitimate source and nothing else.

**4. Switch from report-only to enforcing.**

Change the header name to Content-Security-Policy and keep the report endpoint. Monitor reports for the first days after enforcing.

Expected: violations blocked, reports still flowing for visibility.

**5. Test the whole app.**

Click through every major flow: login, checkout, uploads, embedded content, third-party widgets. CSP breaks the things you forgot to test.

Expected: full app functional with the policy enforcing.

**6. Keep the reports monitored.**

Violation reports are now an early warning system for injected content and for new third parties someone added without telling you. Review them regularly.

Expected: a quiet report stream, with alerts on sudden spikes.

### Variant phrasings

#### Simplest CSP header that works
The four-directive starter in step 1, report-only first, then enforce with the sources you actually need.

#### CSP broke my site, how to fix
Drop back to report-only, read the violation reports to find what got blocked, allowlist those sources, re-enforce.

#### Content security policy for a site with Google Analytics and fonts
Add the analytics and font domains to script-src and style-src (and font-src). The reports in step 2 will show you the exact domains.

### Why it happens
CSP exists because XSS is still everywhere and input sanitization alone keeps failing. The policy flips the model: instead of trying to block every bad script, the browser only runs scripts from sources you named. The minimal setup works because most apps load resources from a handful of origins, so default-deny plus a short allowlist covers reality.

### Edge cases
- **Inline scripts everywhere:** legacy apps with inline event handlers will drown in violations. Either refactor toward external scripts or add the specific hashes, but dont solve it with 'unsafe-inline', which guts the protection.
- **Third-party widgets that load more third parties:** some widgets pull in chains of additional domains. The report-only phase reveals the full chain, allowlist the whole chain or reconsider the widget.
- **Single-page apps with dynamic imports:** make sure script-src covers the origins of lazily loaded chunks, which sometimes live on a different CDN path.
- **Report endpoint gets spammed:** browser extensions and misbehaving clients generate noise. Filter reports by your own user agent patterns before alerting on them.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_TBMjJusfO-xg9FnfrHc3Kg
