# Bypassing CSP with policy injection

PayPal reflected a GET token param into its CSP report-uri, allowing directive injection that dropped Edge's policy and bypassed Chrome's script-src via script-src-elem.

- Payout: $900
- Severity: medium
- Program: Paypal
- Credited: Gareth Heyes
- Disclosed: 2019-06-05
- Write-up quality: 7/10
- Original: https://portswigger.net/blog/bypassing-csp-with-policy-injection
- Library page: https://bugbountylibrary.com/r/blog%3Aportswigger-net-blog-bypassing-csp-with-policy-injection
- Tags: domain:web impact:integrity kind:research platform:research sev:medium tech:chromium technique:fuzzing technique:parser-differential technique:source-review vuln:misconfiguration vuln:xss

**Target:** CSP header report-uri directive on /webapps/xoonboarding endpoint
**Root cause:** The token GET parameter was concatenated unescaped into the CSP report-uri directive, letting an attacker inject arbitrary CSP directives (e.g. `;_` or `;script-src-elem 'unsafe-inline'`).
**Steps:**
1. Request `https://www.paypal.com/webapps/xoonboarding?values=etc&token=SOMETOKEN;_`
2. Observe CSP header ends with `report-uri /webapps/xoonboarding/api/log/csp?token=SOMETOKEN;_`
3. On Edge, the trailing `;_` invalid syntax causes the entire CSP policy to be dropped
4. On Chrome, inject `;script-src-elem 'unsafe-inline'` to override the existing script-src and allow inline script execution
**How found:** While testing PayPal for CSP and mixed-content bypasses, noticed the token GET param was reflected into report-uri; fuzzed Edge to find minimal characters (`;_`) that break the policy, then reasoned that since Chrome ignores invalid directives and injection is at policy end, a directive that overrides script-src was needed — found script-src-elem.
**Exploitation:** Attacker crafts a URL with a malicious token value that injects CSP directives; on Edge the whole policy is dropped, on Chrome script-src-elem overrides script-src, enabling inline script execution (XSS) despite CSP.
**Insight:** When a reflected parameter lands inside a CSP header, treat the policy as injectable: test trailing directives like script-src-elem (overrides script-src) on Chrome and syntax-breaking characters on parsers that drop whole policies on error.
