All posts

Content Security Policy: Putting the Browser on a Security Diet

Web applications have become remarkably powerful.

A modern browser application can execute JavaScript, load scripts from Content Delivery Networks (CDNs), fetch APIs, open WebSockets, create workers, embed other applications, load fonts and images, submit forms, and communicate with dozens of different origins.

That flexibility is useful.

It is also a fantastic playground for attackers.

Content Security Policy (CSP) is one of the mechanisms available to developers for putting some limits around all of that power.

The basic idea is to tell the browser what the application is allowed to load, execute, connect to, and embed — and let the browser enforce those rules.

The current W3C Content Security Policy Level 3 specification defines CSP as a mechanism for controlling resources a page or worker can fetch or execute, along with other security-relevant policy decisions. As of August 2026, the specification is a W3C Working Draft on the Recommendation track.

CSP in One Sentence

If you only remember one thing about CSP, CSP is a browser-enforced policy that reduces what a web application is allowed to do.

For example:

Content-Security-Policy: \
default-src ‘self’; \
script-src ‘self’ \
https://cdn.example.com; \
object-src ‘none’;

Note, I used shell-style ‘\’ to signify “continued on the next line” for readability. Use your imagination. For an actual CSP compliant header, this would all be on one line without any ‘\’.

This tells the browser, roughly:

  • By default, use resources from this application’s origin.
  • JavaScript may come from the application or the specified CDN.
  • Don’t allow plugin objects (that’s the object-src directive).

The injected script from:

https://evil.example/attack.js

doesn’t satisfy the policy.

The browser can block it.

That’s the fundamental security model.

CSP Is Defense in Depth

There is an important qualification here.

CSP is not a replacement for secure application development.

The W3C specification explicitly describes CSP as a defense-in-depth mechanism, rather than the first line of defense against content injection. Input validation and output encoding are still necessary.

Think about the layers.

CSP is the layer that says_,_ “Even if something gets past the application, let’s see what the browser will allow it to do.”

That’s a very useful security boundary.

What Security Problem Is CSP Solving?

One of the primary targets is content injection, particularly cross-site scripting (XSS).

Suppose an attacker manages to inject:

Without CSP, the browser may simply see a perfectly valid script element.

With:

Content-Security-Policy: script-src ’self

the browser sees something different:

The attacker’s problem has become considerably harder.

And that’s the recurring theme throughout CSP, Reduce the privileges available to potentially compromised content.

The W3C specification explicitly identifies reducing application privilege as one of CSP’s goals.

Controlling Script Execution

The most familiar CSP capability is controlling where JavaScript can come from.

Content-Security-Policy: script-src ‘self’ https://cdn.example.com

This establishes an allowlist for script sources, but CSP goes considerably further than simply saying_, “_JavaScript must come from these domains.”

It can also control inline script and dynamic code execution.

That is important because XSS attacks frequently attempt to turn attacker-controlled content into executable JavaScript.

Inline JavaScript

A restrictive CSP can prevent arbitrary inline JavaScript.

For example:

can be blocked unless the policy explicitly permits it.

Likewise, inline event handlers such as:

Originally published on Medium.