Mitigate cross-site scripting (XSS) with a strict Content Security Policy (CSP)

Lukas Weichselbaum
Lukas Weichselbaum

Browser Support

  • Chrome: 52.
  • Edge: 79.
  • Firefox: 52.
  • Safari: 15.4.

Source

Cross-site scripting (XSS), the ability to inject malicious scripts into a web app, has been one of the biggest web security vulnerabilities for over a decade.

Content Security Policy (CSP) is an added layer of security that helps to mitigate XSS. To configure a CSP, add the Content-Security-Policy HTTP header to a web page and set values that control what resources the user agent can load for that page.

This page explains how to use a CSP based on nonces or hashes to mitigate XSS, instead of the commonly used host-allowlist-based CSPs that often leave the page exposed to XSS because they can be bypassed in most configurations.

Key term: A nonce is a random number used only once that you can use to mark a <script> tag as trusted.

Key term: A hash function is a mathematical function that converts an input value into a compressed numerical value called a hash. You can use a hash (for example, SHA-256) to mark an inline <script> tag as trusted.

A Content Security Policy based on nonces or hashes is often called a strict CSP. When an application uses a strict CSP, attackers who find HTML injection flaws generally can't use them to force the browser to execute malicious scripts in a vulnerable document. This is because strict CSP only allows hashed scripts or scripts with the correct nonce value generated on the server, so attackers can't execute the script without knowing the correct nonce for a given response.

Why should you use a strict CSP?

If your site already has a CSP that looks like script-src www.googleapis.com, it's probably not effective against cross-site. This type of CSP is called an allowlist CSP. They require a lot of customization and can be bypassed by attackers.

Strict CSPs based on cryptographic nonces or hashes avoid these pitfalls.

Strict CSP structure

A basic strict Content Security Policy uses one of the following HTTP response headers:

Nonce-based strict CSP

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';