Can XSS be prevented 100% by setting the content security policy as default-src 'self'? Is there any way XSS can happen in that case? One possibility I can think of is injecting user input into one of your scripts dynamically at the server-side, do you agree? Are there any other vulnerabilities you can think of?

  • if you inject something "server-side", it's not XSS, it's just S...
    – dandavis
    Aug 17, 2016 at 22:10
  • @dandavis I think he is referring to stored XSS.
    – Arminius
    Aug 19, 2016 at 0:32

2 Answers 2


CSP in such a configuration should enable the following security measures:

  • Disable inline scripts
  • Disable inline styles
  • Disable all use of dangerous JavaScript functions (e.g. eval)
  • Force all content to be loaded only from the existing domain. This applies to:
    • JavaScript
    • CSS
    • Fonts (e.g. WOFF)
    • Ajax (XmlHttpRequest and similar)
    • WebSockets
    • Video
    • Objects (e.g. Flash, Java applets)
    • SVGs
    • WebGL assets
    • Frames
    • Images
    • Probably some other things I forgot...

As such, XSS should be possible only in cases where resources on the domain can be controlled by an attacker, as you mentioned.

You can lock CSP down further by setting default-src 'none', then explicitly enabling only content types which you are expecting to use on the site. This helps lower your attack surface further by disabling content types like Flash, Java applets, SVGs, canvas, etc. when you're not using them.

One additional vector you may not have considered is Path-Relative Stylesheet Overrides (PRSSI), otherwise known as Relative Path Overwrite (RPO) vulnerabilities. These work by exploiting URL handling behaviour in some CMS software, whereby path characters appear after a script are taken as parameters (e.g. example.com/wiki/index.php/Something shows the Something page). When a path-relative stylesheet is included (e.g. main.css rather than /main.css) this can be sometimes abused. In our example, because main.css is imported relative to the current path, an inclusion in the example URL above would cause the browser to try to load example.com/wiki/index.php/main.css as a stylesheet. If you can create a wiki page called main.css, this would allow you to control the content of that stylesheet, and potentially load malicious CSS (e.g. with the expression directive). You can do the same thing with path relative JavaScript imports. The fix here is to always reference content by its full canonical path.

  • there's no need to worry about "malicious CSS" executing code anymore, and JS is imported relative to the document, not the importing file.
    – dandavis
    Aug 17, 2016 at 20:48
  • "there's no need to worry about malicious CSS executing code anymore" - got a citation on that?
    – Polynomial
    Aug 17, 2016 at 21:37
  • And as for "and JS is imported relative to the document, not the importing file", that's the problem. The browser thinks the document is in a deeper path than it really is.
    – Polynomial
    Aug 17, 2016 at 21:38
  • AFAIK all css execution vectors are at least 5 years outmoded: dec 2011 for expressions, IE9 for behaviors, firefox4 for -moz-binding ... did I miss anything? looking at the % usage of vulnerable browsers suggest it's not worth worrying about anymore; time would be better spent crafting CSPs
    – dandavis
    Aug 17, 2016 at 22:01
  • i should point out that it might be possible to use CSS alone to fool users into doing something dumb, like baiting them to type in a non-clickable url by showing an "error message", but that's not XSS...
    – dandavis
    Aug 17, 2016 at 22:08

default-src 'self' allows XSS via JSONP and content-type sniffing attacks:

Of particular note is our lack of self in our source list. While sourcing JavaScript from self seems relatively safe (and extremely common), it should be avoided when possible.

There are edge cases that any developer must concern themselves with when allowing self as a source for scripts. There may be a forgotten JSONP endpoint that doesn’t sanitize the callback function name. Or, another endpoint that serves user-influenced content with a content-type that could be sniffed by browsers as JavaScript. GitHub has several such endpoints. For example, we return commit diffs as text/plain.


  • CORS has eliminated the need for JSONP, and ALL user input needs sanitized...
    – dandavis
    Aug 18, 2016 at 19:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .