Skip to content
All articles
Web Security

A strict Content Security Policy without unsafe-inline

admin 1 min read

A Content Security Policy (CSP) is a second line of defense against cross-site scripting: even if an attacker injects markup, the browser refuses to run scripts that the policy does not allow.

The target policy

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

No 'unsafe-inline', no 'unsafe-eval', no third-party origins. Everything the page needs is served from your own domain.

What breaks

  • Inline event handlers such as onclick="...". Move them to a JS file and use addEventListener.
  • Inline <script> blocks. Move the code to a static file, or pass data through data-* attributes.
  • Libraries that use eval or new Function. Choose alternatives, or write the few lines of vanilla JS you actually need.
  • Third-party CDNs for fonts and scripts. Self-host them: it is also better for privacy and performance.

Structured data is fine

A <script type="application/ld+json"> block is not executable, so browsers do not apply script-src to it. JSON-LD for SEO keeps working.

Roll it out safely

Start with the Content-Security-Policy-Report-Only header and watch the browser console on every page type. Once it is quiet, switch to the enforcing header. Set it in one place (a Django middleware or the reverse proxy) so it cannot drift between environments.