👨‍💻
Application Security Handbook
  • Application Security Handbook
  • Web Application
    • Authentication
      • Authentication with Login and Password
      • Authentication with Phone Number
      • OAuth 2.0 Authentication
      • Multi-factor Authentication
      • Default Passwords
      • Password Change
      • Password Policy
      • Password Reset
      • Password Storage
      • One Time Password (OTP)
      • Email Address Confirmation
    • Authorization
    • Concept of Trusted Devices
    • Content Security Policy (CSP)
    • Cookie Security
    • Cryptography
      • Cryptographic Keys Management
      • Encryption
      • Hash-based Message Authentication Code (HMAC)
      • Hashing
      • Random Generators
      • Universal Unique Identifier (UUID)
    • Error and Exception Handling
    • File Upload
    • Input Validation
    • JSON Web Token (JWT)
    • Logging and Monitoring
    • Output Encoding
    • Regular Expressions
    • Sensitive Data Management
    • Session Management
    • Transport Layer Protection
    • Vulnerability Mitigation
      • Brute-force
      • Command Injection
      • Cross-Site Request Forgery (CSRF)
      • Cross-Site Scripting (XSS)
      • Mass Parameter Assignment
      • Parameter Pollution
      • Path Traversal
      • Regular Expression Denial of Service (ReDoS)
      • SQL Injection (SQLi)
      • XML External Entity (XXE) Injection
Powered by GitBook
On this page
  • Overview
  • Syntax
  • Directives
  • Source values
  • General
  • Basic Content Security Policy
  • Strict Content Security Policy
  • Nonce-based CSP
  • Hash-based CSP
  • Implementation examples
  • CSP delivery
  • Content-Security-Policy header
  • Content-Security-Policy Meta tag
  • Content-Security-Policy-Report-Only header
  • References
  1. Web Application

Content Security Policy (CSP)

PreviousConcept of Trusted DevicesNextCookie Security

Last updated 1 year ago

Overview

This page contains recommendations for the implementation of the Content Security Policy.

Content Security Policy (CSP) controls which resources are allowed to be loaded or executed by the browser. CSP is a defense-in-depth strategy that aims to mitigate attacks.

Syntax

The Content-Security-Policy HTTP header follows the next syntax:

Content-Security-Policy: <policy-directive>; <policy-directive>

where <policy-directive> consists of <directive> <value> with no internal punctuation.

For example:

Content-Security-Policy: default-src 'self'; frame-ancestors 'self'; form-action 'self'; object-src 'none';

Directives

You can find all directives and their descriptions at .

CSP directives are divided into several classes:

  • control the locations from which certain resource types may be loaded. For example, those directives include:

    • defines the default policy for other fetching directives.

    • specifies valid sources for nested browsing contexts loading using elements such as <frame> and <iframe>.

    • specifies valid sources of images and favicons.

    • specifies valid sources for the <object> and <embed> elements.

    • specifies valid sources for JavaScript and WebAssembly resources.

    • specifies valid sources for stylesheets.

  • establish the properties of a document or worker environment to which a policy applies. For example, those directives include:

    • restricts the URLs which can be used in a document's <base> element.

    • enables a sandbox for the requested resource similar to the <iframe> sandbox attribute.

  • instruct the browser about the locations that the document can navigate to. For example, those directives include:

    • restricts the URLs which can be used as the target of form submissions from a given context.

    • specifies valid parents that may embed a page using <frame>, <iframe>, <object>, or <embed>.

  • control the reporting process of CSP violations.

Source values

Keyword values

Unsafe keyword values

The use of unsafe keyword values significantly weakens the Content Security Policy.

Hosts values

Other values

General

Clarification
  • Send the Content-Security-Policy HTTP header in each HTTP response.

Basic Content Security Policy

Use the following Content Security Policy as a starting point to define your policy:

Content-Security-Policy: default-src 'self'; frame-ancestors 'self'; form-action 'self'; object-src 'none';

This policy assumes that:

  • All resources are hosted by the same domain of a document.

  • There are no inline or eval() for scripts and style resources.

  • There is no need for other websites to frame a website.

  • There are no form-submissions to external websites.

  • There is no need for loading plugins.

Use more tight Content Security Policy for defining a custom policy:

Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; frame-ancestors 'self'; form-action 'self';

This policy allows images, scripts, AJAX, and CSS from the same origin and does not allow any other resources to load such as frame, media, etc.

Strict Content Security Policy

  • // nonce-based
    Content-Security-Policy: default-src 'none'; script-src 'nonce-<RANDOM>' 'strict-dynamic' https: 'unsafe-inline'; object-src 'none'; base-uri 'none';
    // hash-based
    Content-Security-Policy: default-src 'none'; script-src 'sha384-<HASH>' 'strict-dynamic' https: 'unsafe-inline'; object-src 'none'; base-uri 'none';

    Nonce- and hashed-based CSP is a more effective strategy for mitigating XSS attacks. Choosing criteria:

Nonce-based CSP

Nonce-based CSP sets a cryptographically strong random value with each <script> tag that is validated by the browser during execution. Since an attacker can not guess a valid nonce they are not able to execute a malicious code because the browser will block it.

Content-Security-Policy: default-src 'none'; script-src 'nonce-<RANDOM>' 'strict-dynamic' https: 'unsafe-inline'; object-src 'none'; base-uri 'none';
  • Do not create a middleware that replaces all script tags with script nonce=... because attacker-injected scripts will then get the nonces as well. You need an actual HTML templating engine to use nonces.

  • Use nonces of length 16+ bytes.

  • Use a new nonce for each response.

Hash-based CSP

Hash-based CSP sets the hash of JavaScript code foe each <script> tag that is validated by the browser during execution. If there are any changes on that code, the hash will not match and the browser will block the execution.

Content-Security-Policy: default-src 'none'; script-src 'sha384-<HASH>' 'strict-dynamic' https: 'unsafe-inline'; object-src 'none'; base-uri 'none';

<HASH> must be a hash from all inline code within a legitimate inline <script> tag. In case there are multiple inline <script> tags, the syntax is as follows:

Content-Security-Policy: ...; script-src 'sha384-<HASH1>' 'sha384-<HASH1>' ... 'sha384-<HASHN>' 'strict-dynamic' https: 'unsafe-inline';
  • cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A
    # or
    shasum -b -a 384 FILENAME.js | awk '{ print $1 }' | xxd -r -p | base64
  • Content-Security-Policy: ...; script-src 'sha384-a88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=' 'strictdynamic' https: 'unsafe-inline';
    <script src="https://external-website.local/lib-0.0.1.min.js" integrity="sha384-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ="></script>

Implementation examples

Inline scripts

The strict CSP disables any JavaScript code placed inline in the HTML source by default. For example, the following inline code will be blocked by the strict CSP:

<script>
var foo = "314"
</script>

Move it to an external JavaScript file and import to the target document to avoid the block by the strict CSP:

<script src="app.js" nonce="${nonce}"></script>

Inlince event handlers

Inline event handlers, such as onclick, onmouseover, etc. are prevented to be executed by the strict CSP. For example, the following inline event handler code will be blocked by the strict CSP:

<span onclick="doThings();">A thing.</span>

Refactor it as shown below to avoid the block by the strict CSP:

<span id="things">A thing.</span>
<script nonce="${nonce}">
    document.getElementById('things')
        .addEventListener('click', doThings);
</script>

Inline JavaScript URI

Inline JavaScript URI such as <a href="javascript: ..."> is prevented to be executed by the strict CSP. For example, the following JavaScript URI scheme code will be blocked by the strict CSP:

<a href="javascript:linkClicked()">foo</a>

Refactor it as shown below to avoid the block by the strict CSP:

<a id="foo">foo</a>
<script nonce="${nonce}">
    document.getElementById('foo')
        .addEventListener('click', linkClicked);
</script>

CSP delivery

Content-Security-Policy header

Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; frame-ancestors 'self'; form-action 'self';

Content-Security-Policy Meta tag

<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

Content-Security-Policy-Report-Only header

Violations from Content-Security-Policy-Report-Only are printed on the browser's console or delivered to a defined endpoint using report-to or report-uri directives. report-to directive requires the Reporting-Endpoints HTTP header to be set and a named endpoint such as main-endpoint.

Reporting-Endpoints: main-endpoint="https://reports.website.local/main"
Content-Security-Policy-Report-Only: script-src 'self'; object-src 'none'; report-to main-endpoint;

References

You can find all source values and their descriptions at .

will not allow the loading of any resources.

only allow resources from the current origin.

the trust granted to a script in the page due to an accompanying nonce or hash is extended to the scripts it loads.

requires a sample of the violating code to be included in the violation report.

allows using of inline resources.

allows using of dynamic code evaluation such as .

allows enabling specific inline event handlers.

allows the loading of resources from a specific host, path or specific URL. For example, website.local, website.local/api/, or https://website.local/script.js.

allows the loading of resources over a specific scheme. For example, https:, http:, or data:.

is a cryptographic nonce (only used once) to allow scripts. For example, nonce-DhcnhD3khTMePgXwdayK9BsMqXjhguVV.

sha256, sha384, or sha512. Followed by a dash and then the sha* value. For example, sha256-jzgBGA4UWFFmpOBq0JpdsySukE1FrEN5bUpoK8Z29fY=.

Do not use CSP as main and single mitigation layer against Cross-Site Scripting attacks, see the page.

Define CSP as restrictive as possible. Use to check the CSP for possible misconfigurations.

CSP must allow loading and executing the minimum required resources. Ideally, should not find any ways to bypass the CSP.

Use the basic Content Security Policy, see the section.

Use the Content-Security-Policy HTTP header for CSP delivering, see the section.

Use the strict Content Security Policy, see the section.

Use the Content-Security-Policy-Report-Only HTTP header to report and log policy violations, see section.

Use or as a start point for defining your policy:

is more easier to implement and use it on multiple projects because it always has the same structure.

is preferable when pages are served statically or need to be cached by a user-agent or CDN. For example, single page web applications built with frameworks such as Angular, React, Vue, etc. Any changes made to a hashed inline script (including formatting) require the corresponding CSP hash header to be updated.

Generate a nonce using a cryptographically strong generator, see the page.

Calculate a hash of static inline code within <script> tag, see the page. You can use the following commands to generate a hash:

Add the attribute for static inline code within <script> tag.

Passing a CSP in the HTTP header from a server is the best and secure CSP delivery that provides a full CSP defense.

For more detailed examples, see the and sections.

In case the can not be set, you can use the Content-Security-Policy <meta> tag within HTML markup with the http-equiv and content attributes. Unfortunately, this meta tag is not able to use framing protections, sandboxing or CSP violation logging endpoint.

The HTTP header allows reporting CSP violations without enforce them. This means, it can be used as a step to c reate, test and tight a CSP to fit your application needs without breaking functionality. Once you have found the best CSP directives and values for your application, you can deploy it as the Content-Security-Policy header to enforce protection. However, it is possible combining both Content-Security-Policy and Content-Security-Policy-Report-Only headers, which is a good practice.

Cross-Site Scripting
MDN Web Docs: Content-Security-Policy - Directives
Fetch directives
default-src
frame-src
img-src
object-src
script-src
style-src
Document directives
base-uri
sandbox
Navigation Directives
form-action
frame-ancestors
Reporting directives
Other directives
MDN Web Docs: Content-Security-Policy - CSP source values
none
self
strict-dynamic
report-sample
unsafe-inline
unsafe-eval
eval
unsafe-hashes
Host
Scheme
nonce-*
sha*-*
Vulnerability Mitigation: Cross-Site Scripting (XSS)
CSP Evaluator
CSP Evaluator
Cryptography: Random Generators
Cryptography: Hashing
integrity
Content-Security-Policy
Content-Security-Policy-Report-Only
OWASP Cheat Sheet Series - Content Security Policy Cheat Sheet
MDN Web Docs: Content-Security-Policy
Basic Content Security Policy
Content-Security-Policy header
Strict Content Security Policy
Content-Security-Policy-Report-Only header
Nonce-based CSP
Hash-based CSP
Nonce-based CSP
Hash-based CSP
Basic Content Security Policy
Strict Content Security Policy
Content-Security-Policy HTTP header