Whilst using CSP for a slightly different purpose (sandboxing) I realized that a very simple auto clicked link seems to bypass even relatively strict CSP. What I am describing i
CSP is one of the ways to reduce the damage done by XSS, but it is by no means a magic wand that fixes all issues caused by XSS vulnerabilities. This non-goal is also listed explicitly in the CSP specification:
Content Security Policy (CSP) is not intended as a first line of defense against content injection vulnerabilities. Instead, CSP is best used as defense-in-depth, to reduce the harm caused by content injection attacks. As a first line of defense against content injection, server operators should validate their input and encode their output.
If you have to run JavaScript code, but you cannot trust the code, then you could serve the page with a sandbox directive without the allow-same-origin
flag. With this CSP directive, the page will run at a unique security origin, which does not share any state (i.e. cookies, DOM Storage, databases, ...) with the displayed origin. Consequently, injected scripts cannot leak information, because they cannot get the information in the first place.
For example, to allow inline scripts to run, but without access to same-origin data, use:
default-src 'none'; script-src 'unsafe-inline'; sandbox allow-scripts
Don't bother with blacklisting JavaScript methods as suggested by another answer, because 1) you will always overlook a method and 2) disabling JavaScript APIs may break your web application in unexpected ways, and 3) the attacker only needs one hole to do damage, and your (custom) application probably contains at least one method which can be abused by an attacker.