https://www.kayssel.com/newsletter/issue-20/
Skip to main content
Kayssel
Home Series Author Projects About Newsletter
[?]K
Kayssel
Home
Series
Author
Projects
About
Newsletter
Connect with me
CSP for Pentesters: Understanding the Fundamentals
8 min read
October 19, 2025
Site Updates
Comments Available
Drop your thoughts in the comments below! Found a bug or have
feedback? Let me know.
Recent Migration
Migrated from Ghost to Astro. Spot any formatting issues? Report
them!
Email X Mastodon
CSP for Pentesters: Understanding the Fundamentals
Table of contents
Contents
Hi everyone,
A few weeks ago I was knee-deep in a CTF challenge. Found an XSS
vulnerability, felt good about it, crafted my payload, and... nothing.
The page just sat there, mocking me. Turns out the CSP was configured
in this very specific way that blocked everything I tried. Spent the
next hour actually reading the policy line by line, understanding
what was allowed and what wasn't. Eventually got it, but man, it made
me realize how little attention I'd been paying to this header.
So that's what sparked this newsletter. I want to break down how CSP
actually works and, more importantly, where people screw it up.
Quick side note: I'm also working on improving the website right now.
Adding a white theme because apparently some of you don't live in
dark mode like civilized people, plus keybindings and a bunch of
other stuff. Should be ready soon
What CSP Actually Is
Picture this: you're running a nightclub. You don't want random
people wandering in off the street, so you hire a bouncer. That
bouncer has a list, and if you're not on it, you're not getting in.
CSP is essentially that bouncer, but for your browser.
The server sends a policy to the browser saying "hey, only execute
scripts from these specific places I trust." When you try to inject
malicious code from somewhere else, the browser goes "nope, not on
the list" and blocks it. In theory, it's brilliant. In practice,
well, that's why we're here.
Here's what the flow looks like:
Server: "Content-Security-Policy: script-src 'self'"
You:
All of these are inline. A proper CSP blocks them unless
'unsafe-inline' is present. But here's the thing: tons of legacy
applications have inline scripts scattered everywhere. Refactoring
all of that is a massive undertaking, so devs take the easy way out.
They slap 'unsafe-inline' in there "temporarily" and call it a day.
I've seen "temporary" fixes that have been in production for three
years.
'unsafe-eval' is similar but for a different type of code execution.
It allows functions like eval() that take strings and execute them as
code:
eval('alert(1)');
setTimeout('alert(1)', 0);
new Function('alert(1)')();
If you can control what string gets passed to any of these functions,
and 'unsafe-eval' is present, you're in.
Then there are the wildcards. * means any domain. https: means any
HTTPS site (which is basically everything now). data: allows data
URIs, so you can embed code directly in a URL. *.example.com allows
any subdomain. All of these are red flags because they're way too
permissive.
Where Things Break Down
Let me show you the misconfigurations I see over and over again in
real assessments.
The most common one? 'unsafe-inline' just sitting there in the
policy:
Content-Security-Policy: script-src 'self' 'unsafe-inline'
When you see this, your standard XSS payloads work perfectly: