Introduction to Content-Security-Policy (CSP)

|Benni Mack

Injection vulnerabilities, categorized as A03:2021 in the OWASP Top 10 , pose significant threats to web security. These occur when malicious data manipulates an interpreter, potentially leading to unauthorized data access or execution of harmful commands. Cross-Site Scripting (XSS), a common form of injection, enables attackers to execute malicious scripts in users’ browsers, risking data breach and site integrity.

Content Security Policy (CSP) offers a critical defense against such vulnerabilities. It allows developers to define trusted sources for executable scripts, countering XSS and other injection attacks. This blog post will delve into CSP's role in fortifying web applications against these prevalent cyber threats.

Cross-Site Scripting is just the beginning

Cross-Site Scripting (XSS) is a prevalent security vulnerability that can be broadly categorized into two types: reflected and stored XSS. Reflected XSS attacks occur when a malicious script is injected through a user input such as a search form that is immediately returned by web applications. This type of attack is typically delivered via a link containing the malicious script, which, when clicked by a user, executes the script on the user's browser.

On the other hand, stored XSS, also known as persistent XSS, involves injecting a script that is stored on the server or in the database. This script is then served to users as part of regular content. A common vector for stored XSS is a comment on a blog post containing a script.

Decoding Cross-Site Scripting: A Closer Look at Reflected and Stored XSS

These vulnerabilities can be particularly damaging to a Content Management System (CMS). If an attacker successfully executes an XSS attack within a CMS, they could potentially hijack an editor's or admin's session. This is achieved by injecting a script that captures session tokens or cookies and sends them to the attacker. With these credentials, the attacker can gain unauthorized access to the CMS with the same privileges. This could lead to unauthorized content changes, data breaches, or further propagation of the attack within the CMS user base.

CSP to the rescue

Content Security Policy plays a pivotal role in mitigating such risks by restricting the sources from which scripts can be loaded, thus preventing the execution of unauthorized scripts. By implementing a robust CSP, website administrators can significantly reduce the likelihood and impact of both reflected and stored XSS attacks in a CMS environment.

CSP is implemented through HTTP headers, providing instructions to web browsers on safe script execution. The Content-Security-Policy header defines rules about where resources, such as scripts and stylesheets, can be loaded from.

The structure of a CSP header

Here's a typical example of a CSP HTTP header that allows Google Tag Manager, local style sheets, fonts, and JavaScript, while disallowing inline JavaScript:

Content-Security-Policy: default-src 'self';
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  font-src 'self';
  connect-src 'self';
  img-src 'self';
  frame-src 'self';

This policy does the following:

default-src 'self'
Limits fetching of most resources (e.g., fonts, scripts, etc.) to the same origin as the site.
script-src 'self'
Allows scripts from your own domain and from Google Tag Manager.
style-src 'self' 'unsafe-inline'
Permits stylesheets from your own domain and allows inline styles. Note: 'unsafe-inline' is necessary for inline styles; however, it does increase vulnerability, so use it judiciously.
font-src 'self'
Restricts font loading to your domain and to Google Fonts.
connect-src 'self'
Allows the site to send XMLHttpRequests (AJAX requests) to your domain and to Google Analytics.
img-src 'self'
Allows images to be loaded from your domain and Google Analytics.
frame-src 'self'
Permits framing content from your domain and Google Tag Manager.

CSP Support - Level 1, Level 2 and Level 3

By 2023, CSP has expanded further, making various additions to the original standard. Each level of CSP introduces more sophisticated security features. CSP level 1 provides the basic framework for defining trusted content sources. CSP level 2 introduces more directives and adds stricter policy enforcement capabilities, while CSP level 3 further refines this with even more directives and enhancements, such as more refined control over inline script execution.

The support for CSP and its different  levels varies among web browsers:

Google Chrome: Chrome has supported CSP since version 25. It initially supported CSP level 1 and later added support for CSP level 2 and 3, offering more granular control over script sources and style sources.

Mozilla Firefox: Firefox implemented CSP support starting from version 23. Like Chrome, it has progressively enhanced its support from CSP 1 to CSP 3, aligning with evolving web security standards.

Safari (Apple): Safari began its support for CSP with version 7, initially adhering to level 1 directives. Subsequent versions have expanded this support, incorporating more features from CSP levels 2 and 3.

Microsoft Edge: The original Edge browser, based on EdgeHTML, supported CSP from its early versions, aligning closely with the standards set by CSP level 1 and 2. The Chromium-based Edge, released in 2020, supports CSP levels up to 3, similar to Chrome.

Internet Explorer: Internet Explorer has limited support for CSP, starting from version 10. However, its implementation is less comprehensive than other modern browsers, particularly in regards to CSP levels 2 and 3.

In conclusion, most modern web browsers understand and enforce CSP, with variations in the level of support and implementation. This makes CSP a crucial tool in the web developer’s arsenal for preventing the execution of unauthorized scripts, thereby mitigating risks associated with XSS and other injection vulnerabilities.

Note: When using older browsers, or embedded browsers in a Smartphone app, your rules might break: When using the In-App Browser of your Smartphones’ Facebook App, Facebook always injects additional JavaScript code, which will break your CSP enabled site. Older browsers from e.g. 2017 might not understand your CSP rules and will also render sites unusable. It is highly recommended to maintain CSP security and  strictness and not to reduce either for the sake of compatibility with older browsers.

More CSP features

While CSP is very flexible with the existing format from above, there are a few nifty additions to help with special cases and more dynamic use-cases:

Report-Only Mode

What is it?

  • Report-Only mode in CSP allows you to test a policy without enforcing it. This mode sends reports of policy violations to a specified URL but doesn’t block any content that violates the policy.

Example Usage:

Content-Security-Policy-Report-Only: script-src 'self'; report-uri /csp-violation-report-endpoint

  • Here, the CSP is in Report-Only mode. Violations of the script-src 'self' directive will be reported to /csp-violation-report-endpoint, but scripts from other sources will still be executed.

When to use it?

  • It's used when testing a new policy to ensure it doesn't break the site's functionality. After confirming that no legitimate content is blocked, you can switch to enforcing the policy.


What are they?

  • A nonce (number used once) is a random token which is used to whitelist specific inline scripts or styles. Each time the page loads, a new nonce value is generated.

Example Usage:

Content-Security-Policy: script-src 'nonce-XYZ123'

<script nonce="XYZ123"> ... </script>

  • Here, only the script tag with the matching nonce XYZ123 will be allowed to execute.

When to use them?

  • Use nonces when you need to allow specific inline scripts or styles while maintaining a restrictive CSP.


What are they and when to use them?

  • Hashes in CSP allow you to whitelist specific inline scripts or styles based on their cryptographic hash value.
  • They are used when you have static inline scripts or styles that you want to allow without resorting to the less secure 'unsafe-inline' directive.

Example Usage:

Content-Security-Policy: script-src 'sha256-Base64EncodedHash'

<script> ... </script> <!-- Script content here must match the hash -->

  • The hash (e.g., 'sha256-Base64EncodedHash') must match the hash of the inline script's content.

Where do they come from?

  • You generate the hash from the content of your inline script or style. Tools and browser developer consoles can help generate these hashes.

Subresource Integrity (SRI)

What is it?

  • SRI complements CSP by adding another layer of verification for external resources, further safeguarding your site against potential manipulations or attacks.
  • It allows browsers to verify that resources fetched from a server (like JavaScript or CSS files) are exactly as the server intended.
  • It is implemented by adding a cryptographic hash to a resource tag, such as a script or link tag.

Example Usage:

<script src="" 

  • In this example, sha384-Base64EncodedHash is the base64-encoded SHA-384 hash of the file example.js. The browser will calculate the hash of the fetched file and match it with this value. If they don't match, the file is not executed or applied.

When and Why to Use It?

  • Use SRI when loading resources from external sources, especially CDNs, to ensure their integrity.
  • It's particularly useful to protect against the compromise of third-party providers. If a CDN or external source is compromised and the content is altered, SRI will prevent the altered content from being loaded.

Limitations and Considerations:

  • SRI is only effective if the integrity attribute is securely delivered. If an attacker can alter your site's HTML, they can alter the SRI attributes too.
  • It's not suitable for resources that are intended to change frequently, as any change in the resource requires an update of the hash in the integrity attribute.

Usage of 'unsafe-hashes'

What is it and what does it achieve?

  • The 'unsafe-hashes' directive in CSP allows specific inline event handlers (like onclick, onsubmit, etc.) while blocking other inline scripts.
  • It enhances security by permitting only certain inline event handlers without enabling all inline scripts.
  • ‘Unsafe-hashes’ was introduced with CSP Level 3 and helps to overcome scenarios in combination with ‘strict-dynamic’, especially relevant when allowing external services such as Google Maps on your website.

Example Usage:

Content-Security-Policy: script-src 'self' 'unsafe-hashes' 'sha256-Base64EncodedHash'

  • This policy allows scripts from the same origin, specific inline event handlers matching the hash, but blocks other inline scripts.


  • Report-Only Mode is used for testing policies.
  • Nonces allow specific inline scripts/styles and are great for dynamic content.
  • Hashes are used for static inline content.
  • SRI are used in scenarios where you depend on external sources for important scripts or styles.
  • 'unsafe-hashes' selectively permits certain inline event handlers, providing a middle ground between full inline script allowance and complete restriction.

Each of these tools and directives serves a specific purpose in crafting a CSP that balances security needs with functional requirements.

A great resource to learn in-depth about CSP is 

CSP: With great power comes great responsibility

Now you know that you can effectively remove any XSS problem with CSP on your website. But remember: CSP should be tailored to your specific needs and tested thoroughly to ensure it doesn't inadvertently break your site's functionality.

Also, keep in mind that while CSP is a strong security measure, it should be part of a comprehensive security strategy. Sending CSP Headers can be done on the Web Application Firewall, at the webserver configuration such as your Nginx or Apache / htaccess file, but your application should understand and support this.

TYPO3 as a Content Management System supports rendering your content and your admin interface with CSP since version 12, including a configuration interface.

If you need help setting up CSP for your CMS, reach out to us and one of our experts will get in touch with you for consulting.

Get in touch!