Typical Content Security Policy mistakes and omissions
Content Security Policy is an excellent second-line-of-defence safeguard — it gives extra peace of mind for scenarios such as a previously unknown vulnerability being discovered in a 3rd party JavaScript library used by your otherwise well-tested and secure application. You can find out more here.
It comes at a cost — CSP over years evolved as a relatively complex standard, with plenty of extensions and numerous dos and don'ts based on differences in implementation between various browsers. Here are the best practices and most common mistakes in implementing CSP in real world applications:
- DO NOT use
unsafe-inline
orunsafe-eval
— these are, as the name suggests, simply unsafe and allow full CSP bypass using JavaScript code injected in the page if an XSS is found. - DO NOT a classic origin whitelist — long sequence of
script-src 'self' https://example.com
directives are the traditional way of building CSP but it's neither safe nor effective. - DO NOT use
default-src 'self'
— this way you're giving a blanket approval to all kinds of more or less exotic content types, even though you would never use them legitimately on your website (e.g.applet
etc) - DO NOT use
script-src
withoutobject-src
ordefault-src 'none'
— otherwise an XSS bypass is possible using<object>
with a malicious SWF file - DO NOT use wildcard origins (asterisk
*
) or URL schemes — they allow bypass of the policy by including content from completely untrusted domains, or injection through schemes such asjavascript:
- DO use content hashes (e.g.
script-src 'sha256-aBC...'
) for whitelisting trusted inline scripts - DO use nonces combined with "strict dynamic" (e.g.
script-src 'nonce-XXX...' 'strict-dynamic'
) to whitelist trusted scripts that load other scripts (chain loading) - DO set
default-src 'none'
and then allow individual content types using their designated directives — this way you not only make the policy more robust but also improve logging precision (withreport-uri
), because for most browsers reports will use the most general directive that caused the block and, believe me, information that some content was blocked bydefault-src
is pretty useless - DO prevent clickjacking with
frame-ancestors 'none'
directive - DO use
block-all-mixed-content
directive - DO use
upgrade-insecure-requests
directive
This list incorporates guidelines published in CSP Is Dead, Long Live CSP article, as well as our own experience. The WebCookies.org engine now displays warnings based on these guidelines if CSP header is found on your website.