How Content Security Policy Prevents Injection Attacks

Content Security Policy (CSP) is a critical HTTP response header that restricts the resources a browser is allowed to load and execute on a web page. By establishing strict rules for fetching scripts, stylesheets, and data, CSP acts as a robust defense layer designed specifically to prevent code injection attacks, primarily Cross-Site Scripting (XSS). This article breaks down the operational mechanics of CSP, detailing how directive enforcement, script execution restrictions, and reporting mechanisms eliminate malicious payloads.

Restricting Trusted Resource Sources

The primary mechanism of CSP is resource whitelisting through explicit directives. By defining directives like default-src, script-src, and style-src, a web developer can tell the browser exactly which origins are permitted to serve executable code and assets.

When an attacker successfully injects an external script tag—such as <script src="https://attacker.com/malicious.js"></script>—the browser evaluates the source domain against the active script-src directive. If attacker.com is not explicitly permitted in the policy, the browser blocks the network request immediately, preventing the hostile code from loading.

Disabling Inline Execution and Dynamic Code Evaluation

Most injection attacks rely on executing arbitrary inline scripts or abusing dynamic JavaScript execution functions. CSP mitigates this behavior through two default behaviors:

  • Blocking Inline Scripts: By default, CSP disallows the execution of inline <script> elements, inline event handlers (such as onclick="..."), and javascript: URIs. Even if an attacker injects <script>stealData()</script> into a vulnerable comment field, the browser identifies it as an inline script and refuses to run it.
  • Restricting eval(): CSP bans the use of eval(), new Function(), setTimeout(string), and related dynamic string-to-code execution primitives unless the risky 'unsafe-eval' keyword is explicitly permitted. This stops attackers from passing injected strings into dynamic execution sinks.

Implementing Cryptographic Nonces and Hashes

Modern applications often require legitimate inline scripts to function. CSP solves this without weakening security by implementing cryptographic nonces (numbers used once) and SHA hashes:

  • Nonces: A server generates a cryptographically random, single-use token on every HTTP request and includes it in the header: Content-Security-Policy: script-src 'nonce-EDNnf03nceI1nnq'. The developer includes this matching nonce in authorized inline scripts: <script nonce="EDNnf03nceI1nnq">...</script>. Injected scripts lacking this unpredictable value are rejected.
  • Hashes: Developers can calculate the SHA-256 (or higher) hash of a static inline script and specify it in the policy. The browser hashes the script before execution; if the generated hash does not match the policy, execution is blocked.

Preventing Data Exfiltration

A successful injection attack often attempts to transmit sensitive user data—such as session tokens, credentials, or personal information—to a remote server controlled by the attacker. CSP limits this phase of an attack using directives that govern outbound connections:

  • connect-src limits destinations for fetch(), XMLHttpRequest, WebSockets, and EventSource.
  • form-action controls which targets can receive <form> submissions, preventing attackers from injecting actions that submit user inputs to external URLs.

By locking down outbound communications, CSP ensures that even if an attacker manages to execute code in the browser context, they cannot easily exfiltrate captured data.

Monitoring Violations with Reporting Directives

CSP provides a controlled path for deployment through violation reporting. Using the report-to or report-uri directive, the browser sends JSON-formatted reports to a specified endpoint whenever a policy violation occurs.

Developers can also deploy policies using the Content-Security-Policy-Report-Only header. In this mode, the browser logs violations and alerts security teams to potential injection attempts or policy misconfigurations without interrupting page rendering. Once the policy is validated, moving it to standard enforcement blocks all non-compliant scripts automatically.