blueredix logo
medium missing-csp

Content Security Policy not set

A Content Security Policy is a list of trusted sources for the scripts, styles, and embeds your website loads. Without one, a single bug in your application can let an attacker run their code on every visitor's browser.

What this means in plain English

A Content Security Policy (CSP) is a small instruction your website sends to browsers that lists which sources are allowed to provide scripts, styles, images, and other content on your pages. The browser then refuses to load anything from sources that aren’t on the list.

Your site doesn’t currently send this instruction. Without it, the browser default is “allow content from anywhere” — which is what makes a whole category of website attack so damaging.

Why it matters to your business

A common attack pattern is cross-site scripting (XSS, see our XSS article): an attacker finds a way to make your site display content they control — for example a crafted search query, a comment, or a profile field — in a way that the browser interprets as code rather than text. Without a CSP, that code can:

  • Read everything the visitor’s browser has access to on your site, including cookies and form contents.
  • Send all of that to a server the attacker controls.
  • Load further attack code from arbitrary remote locations.
  • Modify what the visitor sees — for example, replace your real login form with a fake one.

A well-tuned CSP turns the same bug into something much smaller. The malicious code can no longer load helpers from outside, can no longer phone home to attacker-controlled servers, and can no longer silently embed fake UI. The bug still exists — but its impact drops substantially.

CSP also gives you a quiet check on third-party tools you didn’t fully vet. If a marketing widget or chat tool tries to load something new, your CSP blocks it (and reports it to you) instead of silently allowing it.

How to fix it

A complete CSP for a real-world site takes some tuning — modern websites use lots of inline scripts and third-party tools, and listing them all takes care. The recommended path is a three-stage rollout that doesn’t break anything along the way.

Stage 1: Watching mode (week 0)

Deploy CSP in report-only mode. The browser logs violations to your server but doesn’t actually block anything yet:

Content-Security-Policy-Report-Only:
  default-src 'self';
  script-src 'self' 'unsafe-inline';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;
  connect-src 'self';
  frame-ancestors 'none';
  report-uri /csp-report;

Watch the reports for a week. Each violation reveals a third-party service, an inline script, or an embed you might have missed.

Stage 2: Tightening (week 2)

Replace the 'unsafe-inline' allowance for scripts with a more secure mechanism: a one-time random value (a “nonce”) attached to each legitimate inline script. Most modern frameworks (Next.js, Rails 7+, Django, Laravel) generate these automatically. Add the specific third-party hosts you actually use to the allowed list.

Stage 3: Enforcement (week 3)

Switch the header name from Content-Security-Policy-Report-Only to Content-Security-Policy. The policy is now in force.

Quick wins even without a full rollout

If a complete CSP is more work than you can take on right now, two narrower headers cover meaningful ground each on their own:

  • frame-ancestors 'none' (or 'self') prevents your site from being loaded inside another website’s iframe — see our X-Frame-Options article.
  • default-src 'self' blocks the long tail of mixed-content fetches for sites that don’t deliberately embed third-party content.

Further reading