CINXE.COM
FAQ - Content Security Policy
<!doctype html> <html class="google" lang="en"> <head> <meta charset="utf-8"> <title>FAQ - Content Security Policy</title> <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&lang=en" rel="stylesheet"> <link href="https://www.google.com/css/maia.css" rel="stylesheet"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link href="style.css" rel="stylesheet"> </head> <body> <div class="maia-header" id="maia-header" role="banner"> <div class="maia-aux"> <div id="product"> <a href="/"> <span class="cspdoc-site-title">Content Security Policy</span> </a> </div> <div class="clear"></div> </div> <div class="maia-nav" id="maia-nav-x" role="navigation"> <div class="maia-aux cspdoc-navbar-content"> <ul> <li><a href="index.html">Introduction</a></li> <li><a href="why-csp.html">Why CSP</a></li> <li><a href="strict-csp.html">Strict CSP</a></li> <li><a href="adopting-csp.html">Adopting CSP</a></li> <li><b>FAQ</b></li> <li><a href="resources.html">Resources</a></li> </ul> </div> </div> <div class="maia-breadcrumb"></div> </div> <div id="maia-main" role="main"> <div class="maia-cols"> <div class="maia-col-9" id="content"> <div id="deprecation-warning"> This documentation is outdated and available for historical reasons only. To learn how to enable strict Content Security Policy in your application, visit <a href="https://web.dev/strict-csp">web.dev/strict-csp</a>. </div> <div class="cspdoc-content" id="article"> <h1>Frequently Asked Questions</h1> <div class="toc"> <ul> <li class="bullet"> <a href="#generating-nonces" target="_self">How do I generate nonces? </a> </li> <li class="bullet"> <a href="#passing-nonces" target="_self">How do I pass nonces to my templates? </a> </li> <li class="bullet"> <a href="#static-content" target="_self">What if my site is static and I can't add nonces to scripts? </a> </li> <li class="bullet"> <a href="#service-workers" target="_self">What if my application uses Service Workers? </a> </li> <li class="bullet"> <a href="#csp-patches" target="_self">How do I make my favorite JS library/widget/CMS compatible with nonce-based CSP? </a> </li> <li class="bullet"> <a href="#comparison" target="_self">Why does the strict policy only set CSP directives that limit script execution? </a> </li> <li class="bullet"> <a href="#problems-with-whitelists" target="_self">Why can't I keep using script whitelists in CSP? </a> </li> <li class="bullet"> <a href="#strict-dynamic-with-whitelists" target="_self">I want to use 'strict-dynamic', but also enforce a URL whitelist; is this possible? </a> </li> <li class="bullet"> <a href="#caveats" target="_self">What kinds of XSS bugs *are not* mitigated by strict CSP? </a> </li> <li class="bullet"> <a href="#can-i-stop-caring-about-xss" target="_self">Does having CSP mean I can stop caring about XSS? </a> </li> </ul> </div> <h1>Adoption</h1> <h2 id="generating-nonces">How do I generate nonces? </h2> <p>Nonces should be cryptographically strong random values, at least 128 bits in length. An example of a Python function to create a nonce is:</p> <pre class=code> def GetCspNonce(): """Returns a random nonce.""" NONCE_LENGTH = 16 return base64.b64encode(os.urandom(NONCE_LENGTH)) </pre> <p><em>Note:</em> It is important that nonces are unpredictable, and that a new nonce is generated for every page load. Otherwise, an attacker who can guess the correct value will be able to inject arbitrary scripts and bypass CSP.</p> <h2 id="passing-nonces">How do I pass nonces to my templates? </h2> <p>This depends on the framework, but it works like passing any other string variable as a parameter to the template system. For example, using Django/Jinja, you would set:</p> <pre class=code> nonce = GetCspNonce() template_values = { 'script_nonce' : nonce } jinja2.render_template('index.html', template_values) </pre> <p>Remember to make sure that the parameter name matches the value in the template!</p> <p>In Closure Templates, nonces are <a href="https://developers.google.com/closure/templates/docs/security#content_security_policy">inserted automatically</a> by the template system based on the <code>ij.csp_nonce</code> value.</p> <h2 id="static-content">What if my site is static and I can't add nonces to scripts? </h2> <p>In some cases, applications need to serve static HTML files without passing them through a template system. There are several approaches that work in this case:</p> <p><strong>Method #1: Use CSP hashes instead of nonces.</strong></p> <p>It's possible to calculate SHA hashes of static inline <code><script></code> blocks with <a href="https://report-uri.io/home/hash">this tool</a>, or by omitting <code>'unsafe-inline'</code> and inspecting CSP violation warnings in the developer console of the browser, containing hashes of blocked scripts, and add them to the policy as <code>'sha256-...'</code>. If the page loads external scripts, they can first be converted to inline <code><script></code> blocks.</p> <p>For example, the following script:</p> <pre class=code> <script src="https://example.org/foo.js"></script> <script src="https://example.org/bar.js"></script> </pre> <p>can be rewritten as:</p> <pre class=code> <body> <script> var scripts = [ 'https://example.org/foo.js', 'https://example.org/bar.js']; scripts.forEach(function(scriptUrl) { var s = document.createElement('script'); s.async = false; s.src = scriptUrl; document.head.appendChild(s); }); </script> ... </body> </pre> <p><em>WARNING: The snippet above assumes that <code>document.head</code> exists. In case it does not, you must provide an alternative node to append scripts to.</em></p> <p>Then, a hash of the loader script can be calculated and the page will work with a policy of:</p> <pre class=code> Content-Security-Policy: script-src 'sha256-...' 'strict-dynamic' 'unsafe-inline' https: </pre> <p><strong>Method #2: Pass the static file through a template system.</strong></p> <p>In some applications a simpler solution is to make the resources non-static: add nonce attributes which will be filled in by the template system, and render them like other application templates.</p> <h2 id="service-workers">What if my application uses Service Workers? </h2> <p>Since Service Workers are bound by the policy set on the response which returns the worker script -- rather than the CSP of the page which loads it -- the simplest solution is to avoid sending a policy in Service Worker responses.</p> <h2 id="csp-patches">How do I make my favorite JS library/widget/CMS compatible with nonce-based CSP? </h2> <p>Many applications have dependencies on external components which might be incompatible with CSP; by refactoring them you can make it possible for your applications and others to adopt a strict CSP policy. Here are examples of useful refactoring work:</p> <ul> <li> <p>Rewriting patterns that are inherently incompatible with CSP (inline event handlers, <code>javascript:</code> URIs) -- both in any web UIs and in the markup generated by JS libraries.</p> </li> <li> <p>Adopting CSP and serving <code>Content-Security-Policy</code> headers (with a useful policy) in server-side components (for example in admin UIs of web frameworks).</p> </li> <li> <p>Adding script nonces, in markup generated server-side or when loading trusted subresources in JS libraries.</p> </li> <li> <p>Implementing changes to facilitate CSP adoption, e.g. adding an "auto-noncing mode" to a template system (<a href="https://developers.google.com/closure/templates/docs/security#content_security_policy">example</a>) or extending a framework to make it easier to set CSP headers.</p> </li> </ul> <p>In some cases, such changes might qualify for a reward under the <a href="https://www.google.com/about/appsecurity/patch-rewards/">Google Patch Rewards</a> program.</p> <h1>Security</h1> <h2 id="comparison">Why does the strict policy only set CSP directives that limit script execution? </h2> <p>In the past, most applications which used CSP have set a number of directives to restrict the loading of various types of resources, e.g. <code>img-src</code>, <code>font-src</code> or <code>style-src</code>. However, these directives do not constrain an attacker who can inject a malicious script into the application; the ability to inject scripts bypasses any other restrictions offered by CSP.</p> <p>Since setting directives other than <code>script-src</code> and <code>object-src</code> doesn't increase the protection against cross-site scripting, and it adds adoption and maintenance costs of CSP, we believe most applications should focus on deploying the baseline strict policy as the most high-impact improvement. Afterwards, it is of course possible to add further directives, depending on the needs of the application.</p> <h2 id="problems-with-whitelists">Why can't I keep using script whitelists in CSP? </h2> <p>The traditional approach of whitelisting domains from which scripts can be loaded is based on the assumption that all responses coming from a trusted domain are safe, and can be executed as scripts. However, this assumption does not hold for modern applications; some common, benign patterns such exposing <a href="https://lcamtuf.blogspot.ch/2011/08/subtle-deadly-problem-with-csp.html">JSONP interfaces</a> and <a href="https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22">hosting copies of the AngularJS library</a> allow attackers to escape the confines of CSP.</p> <p>In practice, while it may not be obvious to application authors, <a href="https://research.google.com/pubs/pub45542.html">the majority of <code>script-src</code> whitelists can be circumvented</a> by an attacker with an XSS bug, and provide little protection against script injection. In contrast, the <a href="strict-csp.html">nonce-based approach</a> does not suffer from these problems and makes it easier to adopt and maintain a more secure policy.</p> <h2 id="strict-dynamic-with-whitelists">I want to use 'strict-dynamic', but also enforce a URL whitelist; is this possible? </h2> <p>On its own, <code>'strict-dynamic'</code> causes the browser to rely only on nonces or hashes and ignore the URI whitelist in <code>script-src</code>, for backwards compatibility reasons. However, it's possible to enforce both a whitelist and nonces with 'strict-dynamic' by setting two policies:</p> <pre class=code> Content-Security-Policy: script-src foo.example.org bar.example.org 'unsafe-inline' Content-Security-Policy: script-src 'nonce-random123' 'strict-dynamic' 'unsafe-inline' https: </pre> <p>The browser will check each script against each policy separately and only allow those which match both policies. In this case, it will accept scripts with a nonce of <code>random123</code> (second policy) which are either inline <code><script></code> blocks or come from <code>{foo,bar}.example.org</code> (first policy).</p> <h2 id="caveats">What kinds of XSS bugs <em>are not</em> mitigated by strict CSP? </h2> <p>Based on data from Google applications, around 25% of XSS bugs are exploitable even in applications which set a strict CSP policy. This includes:</p> <ul> <li> <p>Injections into the body of <code><script></code> elements. If the application doesn't properly escape user input inside a script which contains a valid nonce, malicious data can escape out of strings and inject its own code into the existing script.</p> </li> <li> <p>Injections into the URL of an external <code><script></code>. If attackers control the <code>src</code> parameter of a script with a nonce, they can point the script to a URL they control (sometimes by using an open redirect).</p> </li> <li> <p>Injections into the locations of dynamically created scripts (<code>document.createElement('script')</code>), including into any library functions which create <code>script</code> DOM nodes based on the value of their arguments. This includes some common APIs such as jQuery's <code>.html()</code>, as well as <code>.get()</code> and <code>.post()</code> in jQuery < 3.0.</p> </li> <li> <p>Template injections in Angular applications. An attacker who can inject an Angular template can use it to <a href="https://sites.google.com/site/bughunteruniversity/nonvuln/angularjs-expression-sandbox-bypass">execute arbitrary JavaScript</a>.</p> </li> <li> <p>If the policy contains <code>'unsafe-eval'</code>, injections into <code>eval()</code>, <code>setTimeout()</code> and a few other rarely used APIs.</p> </li> </ul> <p>Developers and security engineers should pay particular attention to such patterns during code reviews and security audits.</p> <h2 id="can-i-stop-caring-about-xss">Does having CSP mean I can stop caring about XSS? </h2> <p>In short, <em>no</em>.</p> <p>CSP is a defense-in-depth technique that can prevent the execution of unwanted scripts, but it's not a substitute for avoiding (and promptly fixing) XSS bugs. In particular, even with a good policy, the following caveats apply:</p> <ul> <li> <p>Not all browsers support CSP and some users will get no protection even if the application sets a safe policy.</p> </li> <li> <p>Even if attackers cannot inject malicious scripts, they may be able to execute other kinds of attacks, such as <a href="https://www.nds.rub.de/media/emma/veroeffentlichungen/2012/08/16/scriptlessAttacks-ccs2012.pdf">scriptless</a> or <a href="http://lcamtuf.coredump.cx/postxss/">post-XSS</a> attempts.</p> </li> <li> <p>A small fraction of XSS vulnerabilities are not mitigated by CSP and if a flaw in your application was caused by such a bug, an attacker could still exploit it.</p> </li> </ul> <p>All that said, it is important to stress that CSP is a useful safety net which can protect applications from the exploitation of most kinds of XSS, for the majority of users.</p> <h2>What about browser support?</h2> <p>The 'strict-dynamic' keyword is available Chrome, Opera and Firefox, and is <a href="https://blogs.windows.com/msedgedev/2017/01/10/edge-csp-2/">under consideration</a> in Edge. Strict CSP policies are backwards-compatible with other browsers, but they do not protect against most XSS bugs. The main benefit they have in older browsers is protecting against bugs due to insecure URI schemes, i.e. they do not allow exploiting XSS via javascript: URIs.</p> </div> <div></div> </div> <div class="maia-col-3 sidebar"> <h2>Site Contents</h2> <div class="maia-aside cspdoc-sitemap-content"> <ul> <li><a href="index.html">Introduction</a></li> <li><a href="why-csp.html">Why CSP</a></li> <li><a href="strict-csp.html">Strict CSP</a></li> <li><a href="adopting-csp.html">Adopting CSP</a></li> <li><a href="faq.html">FAQ</a></li> <li><a href="resources.html">Resources</a></li> </ul> </div> </body> </html>