-
Notifications
You must be signed in to change notification settings - Fork 35
/
index.kramdown.html
824 lines (674 loc) · 38.6 KB
/
index.kramdown.html
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Subresource Integrity</title>
<script src='https://www.w3.org/Tools/respec/respec-w3c-common' class='remove'></script>
<script class='remove'>
var respecConfig = {
// specification status (e.g. WD, LCWD, NOTE, etc.). If in doubt use ED.
// Member-SUBM
specStatus: "REC",
// the specification's short name, as in http://www.w3.org/TR/short-name/
shortName: "SRI",
// if the specification's copyright date is a range of years, specify
// the start date here:
copyrightStart: "2014",
// if there a publicly available Editor's Draft, this is the link
edDraftURI: "https://w3c.github.io/webappsec-subresource-integrity/",
crEnd: "2015-12-15",
previousMaturity: "PR",
previousPublishDate: "2016-05-10",
implementationReportURI: "https://github.com/w3c/webappsec-subresource-integrity/wiki/Links",
// editors, add as many as you like
// only "name" is required
editors: [
{ name: "Devdatta Akhawe", url: "http://devd.me", mailto: "[email protected]", company: "Dropbox, Inc.", companyURL: "https://www.dropbox.com/"},
{ name: "Frederik Braun", url: "https://frederik-braun.com/", mailto: "[email protected]", company: "Mozilla", companyURL: "https://www.mozilla.org/", w3cid: 68466 },
{ name: "François Marier", url: "https://fmarier.org", mailto: "[email protected]", company: "Mozilla", companyURL: "https://www.mozilla.org/" },
{ name: "Joel Weinberger", url: "https://joelweinberger.us/", mailto: "[email protected]", company: "Google, Inc.", companyURL: "https://google.com/" },
],
otherLinks: [{
key: 'Participate',
data: [{
value: 'We are on GitHub.',
href: 'https://github.com/w3c/webappsec-subresource-integrity'
}, {
value: 'File a bug.',
href: 'https://github.com/w3c/webappsec-subresource-integrity/issues'
}, {
value: 'Commit history.',
href: 'https://github.com/w3c/webappsec-subresource-integrity/commits/gh-pages'
}, {
value: 'Mailing list.',
href: 'https://lists.w3.org/Archives/Public/public-webappsec/'
}]
}, {
key: 'Implementation status',
data: [{
value: "Blink/Chromium",
href: "https://code.google.com/p/chromium/issues/detail?id=355467"
}, {
value: "Gecko",
href: "https://bugzilla.mozilla.org/show_bug.cgi?id=992096"
}]
}],
// name of the WG
wg: "Web Application Security Working Group",
// URI of the public WG page
wgURI: "http://www.w3.org/2011/webappsec/",
// name (with the @w3c.org) of the public mailing to which comments are due
wgPublicList: "public-webappsec",
subjectPrefix: "[SRI]",
// URI of the patent status for this WG, for Rec-track documents
// !!!! IMPORTANT !!!!
// This is important for Rec-track documents, do not copy a patent URI from a random
// document unless you know what you're doing. If in doubt ask your friendly neighbourhood
// Team Contact.
wgPatentURI: "http://www.w3.org/2004/01/pp-impl/49309/status",
localBiblio: {
"CSP": {
title: "Content Security Policy 1.1",
href: "http://w3.org/TR/CSP11",
authors: [
"Adam Barth",
"Dan Veditz",
"Mike West"
],
status: "Working Draft",
publisher: "W3C"
},
"MIMETYPE": {
title: "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types",
href: "https://tools.ietf.org/html/rfc2046",
authors: [
"Ned Freed",
"Nathaniel S. Borenstein"
],
status: "Draft Standard",
publisher: "IETF"
},
"RFC4648": {
title: "The Base16, Base32, and Base64 Data Encodings",
href: "https://tools.ietf.org/html/rfc4648",
authors: [
"Simon Josefsson",
],
status: "Proposed Standard",
publisher: "IETF"
},
"RFC6920": {
title: "Naming Things with Hashes",
href: "http://tools.ietf.org/html/rfc6920",
authors: [
"Stephen Farrell",
"Dirk Kutscher",
"Christian Dannewitz",
"Borje Ohlman",
"Ari Keranen",
"Phillip Hallam-Baker",
],
status: "Proposed Standard",
publisher: "IETF"
}
}
};
</script>
</head>
<body>
<section id="abstract">
<p>This specification defines a mechanism by which user agents may verify that
a fetched resource has been delivered without unexpected manipulation.</p>
</section>
<section id="sotd">
<p>A list of changes to this document may be found at
<a href="https://github.com/w3c/webappsec-subresource-integrity">https://github.com/w3c/webappsec-subresource-integrity</a>.</p>
</section>
<section class="informative">
<h2 id="introduction">Introduction</h2>
<p>Sites and applications on the web are rarely composed of resources from
only a single origin. For example, authors pull scripts and styles from a
wide variety of services and content delivery networks, and must trust
that the delivered representation is, in fact, what they expected to
load. If an attacker can trick a user into downloading content from
a hostile server (via <a href="https://www.ietf.org/rfc/rfc1035.txt">DNS</a> poisoning, or other such means), the author has
no recourse. Likewise, an attacker who can replace the file on the Content
Delivery Network (CDN) server has the ability to inject arbitrary content.</p>
<p>Delivering resources over a secure channel mitigates some of this risk: with
<a href="https://tools.ietf.org/html/rfc5246">TLS</a>, <a href="https://tools.ietf.org/html/rfc6797">HSTS</a>, and <a href="https://tools.ietf.org/html/rfc7469">pinned public keys</a>, a user agent can be fairly certain
that it is indeed speaking with the server it believes it’s talking to. These
mechanisms, however, authenticate <em>only</em> the server, <em>not</em> the content. An
attacker (or administrator) with access to the server can manipulate content with
impunity. Ideally, authors would not only be able to pin the keys of a
server, but also pin the <em>content</em>, ensuring that an exact representation of
a resource, and <em>only</em> that representation, loads and executes.</p>
<p>This document specifies such a validation scheme, extending two HTML elements
with an <code>integrity</code> attribute that contains a cryptographic hash
of the representation of the resource the author expects to load. For instance,
an author may wish to load some framework from a shared server rather than hosting it
on their own origin. Specifying that the <em>expected</em> SHA-384 hash of
<code>https://example.com/example-framework.js</code>
is <code>Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7</code> means
that the user agent can verify that the data it loads from that URL matches
that expected hash before executing the JavaScript it contains. This
integrity verification significantly reduces the risk that an attacker can
substitute malicious content.</p>
<p>This example can be communicated to a user agent by adding the hash to a
<code>script</code> element, like so:</p>
<pre class="example"><code><script src="https://example.com/example-framework.js"
integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7"
crossorigin="anonymous"></script>
</code></pre>
<p>Scripts, of course, are not the only response type which would benefit
from integrity validation. The scheme specified here also applies to <code>link</code>
and future versions of this specification are likely to expand this coverage.</p>
<section>
<h3 id="goals">Goals</h3>
<ol>
<li>
<p>Compromise of a third-party service should not automatically mean
compromise of every site which includes its scripts. Content authors
will have a mechanism by which they can specify expectations for
content they load, meaning for example that they could load a
<em>specific</em> script, and not <em>any</em> script that happens to have a
particular URL.</p>
</li>
<li>
<p>The verification mechanism should have error-reporting functionality which
would inform the author that an invalid response was received.</p>
</li>
</ol>
</section>
<!-- /Introduction::Goals -->
<section>
<h3 id="use-casesexamples">Use Cases/Examples</h3>
<section>
<h4 id="resource-integrity">Resource Integrity</h4>
<ul>
<li>
<p>An author wishes to use a content delivery network to improve performance
for globally-distributed users. It is important, however, to ensure that
the CDN’s servers deliver <em>only</em> the code the author expects them to
deliver. To mitigate the risk that a CDN compromise (or unexpectedly malicious
behavior) would change that site in unfortunate ways, the following
<a href="#dfn-integrity-metadata">integrity metadata</a> is added to the <code>link</code> element included on the page:</p>
<pre class="example"><code><link rel="stylesheet" href="https://site53.example.net/style.css"
integrity="sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB"
crossorigin="anonymous">
</code></pre>
</li>
<li>
<p>An author wants to include JavaScript provided by a third-party
analytics service. To ensure that only the code that has been carefully
reviewed is executed, the author generates <a href="#dfn-integrity-metadata">integrity metadata</a> for
the script, and adds it to the <code>script</code> element:</p>
<pre class="example"><code><script src="https://analytics-r-us.example.com/v1.0/include.js"
integrity="sha384-MBO5IDfYaE6c6Aao94oZrIOiC6CGiSN2n4QUbHNPhzk5Xhm0djZLQqTpL0HzTUxk"
crossorigin="anonymous"></script>
</code></pre>
</li>
<li>
<p>A user agent wishes to ensure that JavaScript code running in high-privilege HTML
contexts (for example, a browser’s New Tab page) aren’t manipulated before display.
<a href="#dfn-integrity-metadata">Integrity metadata</a> mitigates the risk that altered JavaScript will run
in these pages’ high-privilege contexts.</p>
</li>
</ul>
</section>
<!-- Introduction::UseCases::Integrity -->
</section>
<!-- /Introduction::Use Cases -->
</section>
<!-- /Introduction -->
<section id="conformance">
<p>Conformance requirements phrased as algorithms or specific steps can be
implemented in any manner, so long as the end result is equivalent. In
particular, the algorithms defined in this specification are intended to
be easy to understand and are not intended to be performant. Implementers
are encouraged to optimize.</p>
<section>
<h3 id="key-concepts-and-terminology">Key Concepts and Terminology</h3>
<p>This section defines several terms used throughout the document.</p>
<p>The term <dfn>digest</dfn> refers to the base64-encoded result of
executing a cryptographic hash function on an arbitrary block of data.</p>
<p>The term <dfn>origin</dfn> is defined in the Origin specification.
[[!RFC6454]]</p>
<p>The <dfn>representation data</dfn> and <dfn>content encoding</dfn> of a resource
are defined by <a href="https://tools.ietf.org/html/rfc7231#section-3">RFC7231, section 3</a>. [[!RFC7231]]</p>
<p>A <dfn>base64 encoding</dfn> is defined in <a href="https://tools.ietf.org/html/rfc4648#section-4">RFC 4648, section 4</a>.
[[!RFC4648]]</p>
<p>The <dfn>SHA-256</dfn>, <dfn>SHA-384</dfn>, and <dfn>SHA-512</dfn> are part
of the <dfn>SHA-2</dfn> set of cryptographic hash functions defined by the
NIST in <a href="http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf">“FIPS PUB 180-4: Secure Hash Standard (SHS)”</a>.</p>
</section>
<section>
<h3 id="grammatical-concepts">Grammatical Concepts</h3>
<p>The Augmented Backus-Naur Form (ABNF) notation used in this document is
specified in RFC5234. [[!ABNF]]</p>
<p><a href="https://tools.ietf.org/html/rfc5234#appendix-B.1">Appendix B.1</a> of [[!ABNF]] defines <code><dfn>VCHAR</dfn></code>
(printing characters).</p>
<p><code><dfn>WSP</dfn></code> (white space) characters are defined in Section
<a href="http://www.w3.org/TR/html5/infrastructure.html#space-character">2.4.1 Common parser idioms</a> of the HTML 5 specification as
<code>White_Space characters</code>.</p>
</section>
</section>
<section>
<h2 id="framework">Framework</h2>
<p>The integrity verification mechanism specified here boils down to the
process of generating a sufficiently strong cryptographic digest for a
resource, and transmitting that digest to a user agent so that it may be
used to verify the response.</p>
<section>
<h3 id="integrity-metadata">Integrity metadata</h3>
<p>To verify the integrity of a response, a user agent requires <dfn>integrity
metadata</dfn> as part of the <a href="https://fetch.spec.whatwg.org/#concept-request-integrity-metadata">request</a>. This metadata consists of the following
pieces of information:</p>
<ul>
<li>cryptographic hash function (“alg”)</li>
<li><a href="#dfn-digest">digest</a> (“val”)</li>
<li>options (“opt”)</li>
</ul>
<p>The hash function and digest MUST be provided in order to validate a
response’s integrity.</p>
<p class="note">At the moment, no options are defined. However, future versions of
the spec may define options, such as MIME types [[!MIMETYPE]].</p>
<p>This metadata MUST be encoded in the same format as the <code>hash-source</code> (without the single quotes)
in <a href="http://www.w3.org/TR/CSP2/#source-list-syntax">section 4.2 of the Content Security Policy Level 2 specification</a>.</p>
<p>For example, given a script resource containing only the string <code>alert('Hello, world.');</code>,
an author might choose <a href="#dfn-sha-2">SHA-384</a> as a hash function.
<code>H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO</code> is the base64-encoded
digest that results. This can be encoded as follows:</p>
<pre class="example"><code>sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO
</code></pre>
<div class="note">
<p>Digests may be generated using any number of utilities. <a href="https://www.openssl.org/">OpenSSL</a>, for
example, is quite commonly available. The example in this section is the
result of the following command line:</p>
<pre><code>echo -n "alert('Hello, world.');" | openssl dgst -sha384 -binary | openssl base64 -A
</code></pre>
</div>
</section>
<!-- /Framework::Required metadata -->
<section>
<h3 id="cryptographic-hash-functions">Cryptographic hash functions</h3>
<p>Conformant user agents MUST support the <a href="#dfn-sha-2">SHA-256</a>, <a href="#dfn-sha-2">SHA-384</a>
and <a href="#dfn-sha-2">SHA-512</a> cryptographic hash functions for use as part of a
request’s <a href="#dfn-integrity-metadata">integrity metadata</a> and MAY support additional hash functions.</p>
<p>User agents SHOULD refuse to support known-weak hashing functions like MD5 or
SHA-1 and SHOULD restrict supported hashing functions to those known to be
collision-resistant. Additionally, user agents SHOULD re-evaluate their
supported hash functions on a regular basis and deprecate support for those
functions that have become insecure. See <a href="#hash-collision-attacks">Hash collision attacks</a>.</p>
<section>
<h4 id="agility">Agility</h4>
<p>Multiple sets of <a href="#dfn-integrity-metadata">integrity metadata</a> may be associated with a single
resource in order to provide agility in the face of future cryptographic discoveries.
For example, the resource described in the previous section may be described
by either of the following hash expressions:</p>
<pre class="example"><code>sha384-dOTZf16X8p34q2/kYyEFm0jh89uTjikhnzjeLeF0FHsEaYKb1A1cv+Lyv4Hk8vHd
sha512-Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw==
</code></pre>
<p>Authors may choose to specify both, for example:</p>
<pre class="example"><code><script src="hello_world.js"
integrity="sha384-dOTZf16X8p34q2/kYyEFm0jh89uTjikhnzjeLeF0FHsEaYKb1A1cv+Lyv4Hk8vHd
sha512-Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw=="
crossorigin="anonymous"></script>
</code></pre>
<p>In this case, the user agent will choose the strongest hash function in the
list, and use that metadata to validate the response (as described below in
the “<a href="#parse-metadata">parse metadata</a>” and “<a href="#get-the-strongest-metadata-from-set">get the strongest metadata from
set</a>” algorithms).</p>
<p>When a hash function is determined to be insecure, user agents SHOULD deprecate
and eventually remove support for integrity validation using the insecure hash
function. User agents MAY check the validity of responses using a digest based on
a deprecated function.</p>
<p>To allow authors to switch to stronger hash functions without being held back by older
user agents, validation using unsupported hash functions acts like no integrity value
was provided (see the “<a href="#does-response-match-metadatalist">Does response match metadataList</a>” algorithm below).
Authors are encouraged to use strong hash functions, and to begin migrating to
stronger hash functions as they become available.</p>
</section>
<!-- /Framework::Cryptographic hash functions::Agility -->
<section>
<h4 id="priority">Priority</h4>
<p>User agents must provide a mechanism for determining the relative priority of two
hash functions and return the empty string if the priority is equal. That is, if
a user agent implemented a function like <dfn>getPrioritizedHashFunction(a,
b)</dfn> it would return the hash function the user agent considers the most
collision-resistant. For example, <code>getPrioritizedHashFunction('sha256',
'sha512')</code> would return <code>'sha512'</code> and <code>getPrioritizedHashFunction('sha256',
'sha256')</code> would return the empty string.</p>
<p class="note">The <dfn>getPrioritizedHashFunction</dfn> is an internal
implementation detail. It is not an API that implementors
provide to web applications. It is used in this document
only to simplify the algorithm description.</p>
</section>
<!-- /Framework::Cryptographic hash functions::Priority -->
</section>
<!-- /Framework::Cryptographic hash functions -->
<section>
<h3 id="response-verification-algorithms">Response verification algorithms</h3>
<section>
<h4 id="apply-algorithm-to-response">Apply <var>algorithm</var> to <var>response</var></h4>
<ol>
<li>Let <var>result</var> be the result of <a href="#apply-algorithm-to-response">applying <var>algorithm</var></a>
to the <a href="https://tools.ietf.org/html/rfc7231#section-3">representation data</a> without any content-codings
applied, except when the user agent intends to consume the content with
content-encodings applied. In the latter case, let <var>result</var> be
the result of applying <var>algorithm</var> to the <a href="https://tools.ietf.org/html/rfc7231#section-3">representation data</a>.</li>
<li>Let <var>encodedResult</var> be result of base64-encoding
<var>result</var>.</li>
<li>Return <var>encodedResult</var>.</li>
</ol>
</section>
<!-- Algorithms::apply -->
<section>
<h4 id="is-response-eligible-for-integrity-validation">Is <var>response</var> eligible for integrity validation</h4>
<p>In order to mitigate an attacker’s ability to read data cross-origin by
brute-forcing values via integrity checks, responses are only eligible for such
checks if they are same-origin or are the result of explicit access granted to
the loading origin via Cross Origin Resource Sharing [[!CORS]].</p>
<p class="note">As noted in <a href="https://tools.ietf.org/html/rfc6454#section-4">RFC6454, section 4</a>, some user agents use
globally unique identifiers for each file URI. This means that
resources accessed over a <code>file</code> scheme URL are unlikely to be
eligible for integrity checks.</p>
<p class="note">Being in a <a href="https://w3c.github.io/webappsec-secure-contexts/">Secure Context</a> (e.g., a document delivered over HTTPS) is not
necessary for the use of integrity validation. Because resource integrity is
only an application level security tool, and it does not change the security
state of the user agent, a Secure Context is unnecessary. However, if integrity
is used in something other than a Secure Context (e.g., a document delivered
over HTTP), authors should be aware that the integrity provides <em>no security
guarantees at all</em>. For this reason, authors should only deliver integrity
metadata in a Secure Context. See <a href="#non-secure-contexts-remain-non-secure">Non-secure contexts remain non-secure</a> for
more discussion.</p>
<p>The following algorithm details these restrictions:</p>
<ol>
<li>Let <var>response</var> be the response that results from
<a href="https://fetch.spec.whatwg.org/#concept-fetch">fetching</a> the <var>resource</var>.</li>
<li>If the <var>response</var> <a href="https://fetch.spec.whatwg.org/#concept-response-type">type</a> is <code>basic</code>,
<code>cors</code> or <code>default</code>, return <code>true</code>.</li>
<li>Return <code>false</code>.</li>
</ol>
<div class="note">
<p>The <a href="https://fetch.spec.whatwg.org/#concept-response-type">response types</a> are defined by the Fetch
specification [[!FETCH]] and refer to the following:</p>
<ul>
<li><code>basic</code> is a same-origin response, and thus the requestor has full access
to read the body.</li>
<li><code>cors</code> is a valid response to a cross-origin, CORS-enabled request, and thus
again the requestor has full access to read the body.</li>
<li><code>default</code> is a valid response that is generated by a Service Worker as a
response to the request, so its body, too, is fully readable by the requestor.</li>
</ul>
</div>
</section>
<!-- Algorithms::eligible -->
<section>
<h4 id="parse-metadata">Parse <var>metadata</var>.</h4>
<p>This algorithm accepts a string, and returns either <code>no metadata</code>, or a set of
valid hash expressions whose hash functions are understood by
the user agent.</p>
<ol>
<li>Let <var>result</var> be the empty set.</li>
<li>Let <var>empty</var> be equal to <code>true</code>.</li>
<li>For each <var>token</var> returned by <a href="http://www.w3.org/TR/html5/infrastructure.html#split-a-string-on-spaces">splitting <var>metadata</var> on
spaces</a>:
<ol>
<li>Set <var>empty</var> to <code>false</code>.</li>
<li>If <var>token</var> is not a valid metadata, skip the remaining
steps, and proceed to the next token.</li>
<li>Parse <var>token</var> per the grammar in <a href="#dfn-integrity-metadata">integrity metadata</a>.</li>
<li>Let <var>algorithm</var> be the <var>alg</var> component of
<var>token</var>.</li>
<li>If <var>algorithm</var> is a hash function recognized by the user
agent, add the parsed <var>token</var> to <var>result</var>.</li>
</ol>
</li>
<li>Return <code>no metadata</code> if <var>empty</var> is <code>true</code>, otherwise return
<var>result</var>.</li>
</ol>
</section>
<!-- Algorithms::parse -->
<section>
<h4 id="get-the-strongest-metadata-from-set">Get the strongest metadata from <var>set</var>.</h4>
<ol>
<li>Let <var>result</var> be the empty set and <var>strongest</var> be the empty
string.</li>
<li>For each <var>item</var> in <var>set</var>:
<ol>
<li>If <var>result</var> is the empty set, add <var>item</var> to
<var>result</var> and set <var>strongest</var> to <var>item</var>, skip
to the next <var>item</var>.</li>
<li>Let <var>currentAlgorithm</var> be the <var>alg</var> component of
<var>strongest</var>.</li>
<li>Let <var>newAlgorithm</var> be the <var>alg</var> component of
<var>item</var>.</li>
<li>If the result of <a href="#dfn-getprioritizedhashfunction-a-b"><code>getPrioritizedHashFunction(currentAlgorithm, newAlgorithm)</code></a>
is the empty string, add <var>item</var> to <var>result</var>. If the
result is <var>newAlgorithm</var>, set <var>strongest</var> to
<var>item</var>, set <var>result</var> to the empty set, and add
<var>item</var> to <var>result</var>.</li>
</ol>
</li>
<li>Return <var>result</var>.</li>
</ol>
</section>
<!-- /Algorithms::get the strongest metadata -->
<section>
<h4 id="does-response-match-metadatalist">Does <var>response</var> match <var>metadataList</var>?</h4>
<ol>
<li>Let <var>parsedMetadata</var> be the result of
<a href="#parse-metadata">parsing <var>metadataList</var></a>.</li>
<li>If <var>parsedMetadata</var> is <code>no metadata</code>, return <code>true</code>.</li>
<li>If <a href="#is-response-eligible-for-integrity-validation"><var>response</var> is not eligible for integrity
validation</a>, return <code>false</code>.</li>
<li>If <var>parsedMetadata</var> is the empty set, return <code>true</code>.</li>
<li>Let <var>metadata</var> be the result of <a href="#get-the-strongest-metadata-from-set">getting the strongest
metadata from <var>parsedMetadata</var></a>.</li>
<li>For each <var>item</var> in <var>metadata</var>:
<ol>
<li>Let <var>algorithm</var> be the <var>alg</var> component of
<var>item</var>.</li>
<li>Let <var>expectedValue</var> be the <var>val</var> component of
<var>item</var>.</li>
<li>Let <var>actualValue</var> be the result of <a href="#apply-algorithm-to-response">applying
<var>algorithm</var> to <var>response</var></a>.</li>
<li>If <var>actualValue</var> is a case-sensitive match for
<var>expectedValue</var>, return <code>true</code>.</li>
</ol>
</li>
<li>Return <code>false</code>.</li>
</ol>
<p>This algorithm allows the user agent to accept multiple, valid strong hash
functions. For example, a developer might write a <code>script</code> element such as:</p>
<pre class="example"><code><script src="https://example.com/example-framework.js"
integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7
sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB"
crossorigin="anonymous"></script>
</code></pre>
<p>which would allow the user agent to accept two different content payloads, one
of which matches the first SHA384 hash value and the other matches the second
SHA384 hash value.</p>
<p class="note">User agents may allow users to modify the result of this algorithm via user
preferences, bookmarklets, third-party additions to the user agent, and other
such mechanisms. For example, redirects generated by an extension like
<a href="https://www.eff.org/https-everywhere">HTTPS Everywhere</a> could load and execute
correctly, even if the HTTPS version of a resource differs from the HTTP
version.</p>
<p class="note">This algorithm returns <code>false</code> if the response is not <a href="#is-response-eligible-for-integrity-validation">eligible</a> for integrity
validation since Subresource Integrity requires CORS, and it is a logical error
to attempt to use it without CORS. Additionally, user agents SHOULD report a
warning message to the developer console to explain this failure.</p>
</section>
<!-- Algorithms::Match -->
</section>
<!-- Algorithms -->
<section>
<h3 id="verification-of-html-document-subresources">Verification of HTML document subresources</h3>
<p>A variety of HTML elements result in requests for resources that are to be
embedded into the document, or executed in its context. To support integrity
metadata for some of these elements, a new <code>integrity</code> attribute is added to
the list of content attributes for the <code>link</code> and <code>script</code> elements.</p>
<p>A corresponding <code>integrity</code> IDL attribute which <a href="http://www.w3.org/TR/html5/infrastructure.html#reflect">reflects</a> the
value each element’s <code>integrity</code> content attribute is added to the
<code>HTMLLinkElement</code> and <code>HTMLScriptElement</code> interfaces.</p>
<p class="note">A future revision of this specification is likely to include integrity support
for all possible subresources, i.e., <code>a</code>, <code>audio</code>, <code>embed</code>, <code>iframe</code>, <code>img</code>,
<code>link</code>, <code>object</code>, <code>script</code>, <code>source</code>, <code>track</code>, and <code>video</code> elements.</p>
</section>
<section>
<h4 id="the-integrity-attribute">The <code>integrity</code> attribute</h4>
<p>The <code>integrity</code> attribute represents <a href="#dfn-integrity-metadata">integrity metadata</a> for an element.
The value of the attribute MUST be either the empty string, or at least one
valid metadata as described by the following ABNF grammar:</p>
<pre><code>integrity-metadata = *WSP hash-with-options *( 1*WSP hash-with-options ) *WSP / *WSP
hash-with-options = hash-expression *("?" option-expression)
option-expression = *VCHAR
hash-algo = <hash-algo production from [Content Security Policy Level 2, section 4.2]>
base64-value = <base64-value production from [Content Security Policy Level 2, section 4.2]>
hash-expression = hash-algo "-" base64-value
</code></pre>
<p>The <code>integrity</code> IDL attribute must <a href="http://www.w3.org/TR/html5/infrastructure.html#reflect">reflect</a> the <code>integrity</code> content attribute.</p>
<p><code>option-expression</code>s are associated on a per <code>hash-expression</code> basis and are
applied only to the <code>hash-expression</code> that immediately precedes it.</p>
<p>In order for user agents to remain fully forwards compatible with future
options, the user agent MUST ignore all unrecognized <code>option-expression</code>s.</p>
<p class="note">Note that while the <code>option-expression</code> has been reserved in the syntax, no
options have been defined. It is likely that a future version of the spec will
define a more specific syntax for options, so it is defined here as broadly
as possible.</p>
</section>
<!-- /Framework::HTML::integrity -->
<section>
<h4 id="element-interface-extensions">Element interface extensions</h4>
<section>
<h5 id="htmllinkelement">HTMLLinkElement</h5>
<dl title="partial interface HTMLLinkElement" class="idl">
<dt>attribute DOMString integrity</dt>
<dd>The value of this element’s <code>integrity</code> attribute</dd>
</dl>
</section>
<!-- /Framework::HTML::Interface extensions::HTMLLinkElement -->
<section>
<h5 id="htmlscriptelement">HTMLScriptElement</h5>
<dl title="partial interface HTMLScriptElement" class="idl">
<dt>attribute DOMString integrity</dt>
<dd>The value of this element’s <code>integrity</code> attribute</dd>
</dl>
</section>
<!-- /Framework::HTML::Interface extensions::HTMLScriptElement -->
</section>
<!-- /Framework::HTML::Interface extensions -->
<section>
<h4 id="handling-integrity-violations">Handling integrity violations</h4>
<p>The user agent will refuse to render or execute responses that fail an integrity
check, instead returning a network error as defined in Fetch [[!FETCH]].</p>
<p class="note">On a failed integrity check, an <code>error</code> event is fired. Developers
wishing to provide a canonical fallback resource (e.g., a resource not served
from a CDN, perhaps from a secondary, trusted, but slower source) can catch this
<code>error</code> event and provide an appropriate handler to replace the
failed resource with a different one.</p>
</section>
<section>
<h5 id="elements">Elements</h5>
<section>
<h6 id="the-link-element-for-stylesheets">The <code>link</code> element for stylesheets</h6>
<p>Whenever a user agent attempts to <a start="4" href="http://www.w3.org/TR/html5/document-metadata.html#concept-link-obtain">obtain a resource</a> pointed to by a
<code>link</code> element that has a <code>rel</code> attribute with the keyword of <code>stylesheet</code>,
modify step 4 to read:</p>
<p>Do a potentially CORS-enabled fetch of the resulting absolute URL, with the
mode being the current state of the element’s crossorigin content attribute,
the origin being the origin of the link element’s Document, the default origin
behavior set to taint, and the <a href="#dfn-integrity-metadata">integrity metadata</a> of the request set to the
value of the element’s <code>integrity</code> attribute.</p>
</section>
<!-- /Framework::HTML::link -->
<section>
<h6 id="the-script-element">The <code>script</code> element</h6>
<p>Replace step 14.1 of HTML5’s <a start="6" href="http://www.w3.org/TR/html5/scripting-1.html#prepare-a-script">“prepare a script” algorithm</a> with:</p>
<ol>
<li>Let <var>src</var> be the value of the element’s <code>src</code> attribute and
the request’s associated <a href="#dfn-integrity-metadata">integrity metadata</a> be the value of the element’s
<code>integrity</code> attribute.</li>
</ol>
</section>
<!-- /Framework::HTML::Elements::script -->
</section>
<!-- /Framework::HTML::Elements -->
</section>
<!-- /Framework -->
<section>
<h2 id="proxies">Proxies</h2>
<p>Optimizing proxies and other intermediate servers which modify the
responses MUST ensure that the digest associated
with those responses stays in sync with the new content. One option
is to ensure that the <a href="#dfn-integrity-metadata">integrity metadata</a> associated with
resources is updated. Another
would be simply to deliver only the canonical version of resources
for which a page author has requested integrity verification.</p>
<p>To help inform intermediate servers, those serving the resources SHOULD
send along with the resource a <a href="https://tools.ietf.org/html/rfc7234#section-5.2"><code>Cache-Control</code></a> header
with a value of <a href="https://tools.ietf.org/html/rfc7234#section-5.2.1.6"><code>no-transform</code></a>.</p>
</section>
<!-- /Implementation -->
<section class="informative">
<h2 id="security-considerations">Security Considerations</h2>
<section>
<h3 id="non-secure-contexts-remain-non-secure">Non-secure contexts remain non-secure</h3>
<p><a href="#dfn-integrity-metadata">Integrity metadata</a> delivered by a context that is not a <a href="https://w3c.github.io/webappsec-secure-contexts/">Secure Context</a>,
such as an HTTP page, only protects an origin against a compromise of the
server where an external resources is hosted. Network attackers can alter the
digest in-flight (or remove it entirely, or do absolutely anything else to the
document), just as they could alter the response the hash is meant to validate.
Thus, it is recommended that authors deliver integrity metadata only to a
<a href="https://w3c.github.io/webappsec-secure-contexts/">Secure Context</a>. See also <a href="http://www.w3.org/2001/tag/doc/web-https">securing the web</a>.</p>
</section>
<!-- /Security::Non-secure contexts remain non-secure -->
<section>
<h3 id="hash-collision-attacks">Hash collision attacks</h3>
<p>Digests are only as strong as the hash function used to generate them. It is
recommended that user agents refuse to support known-weak hashing functions and
limit supported algorithms to those known to be collision resistant. Examples of
hashing functions that are not recommended include MD5 and SHA-1. At the time of
writing, SHA-384 is a good baseline.</p>
<p>Moreover, it is recommended that user agents re-evaluate their supported hash
functions on a regular basis and deprecate support for those functions shown to
be insecure. Over time, hash functions may be shown to be much weaker than
expected and, in some cases, broken, so it is important that user agents stay
aware of these developments.</p>
</section>
<!-- /Security::Hash collision -->
<section>
<h3 id="cross-origin-data-leakage">Cross-origin data leakage</h3>
<p>This specification requires the <a href="http://www.w3.org/TR/html5/infrastructure.html#cors-settings-attributes">CORS settings attribute</a> to be present on
integrity-protected cross-origin requests. If that requirement were omitted,
attackers could violate the <a href="http://www.w3.org/Security/wiki/Same_Origin_Policy">same-origin policy</a> and determine whether
a cross-origin resource has certain content.</p>
<p>Attackers would attempt to load the resource with a known digest, and
watch for load failures. If the load fails, the attacker could surmise
that the response didn’t match the hash and thereby gain some insight into
its contents. This might reveal, for example, whether or not a user is
logged into a particular service.</p>
<p>Moreover, attackers could brute-force specific values in an otherwise
static resource. Consider a JSON response that looks like this:</p>
<pre class="example"><code>{'status': 'authenticated', 'username': 'admin'}
</code></pre>
<p>An attacker could precompute hashes for the response with a variety of
common usernames, and specify those hashes while repeatedly attempting
to load the document. A successful load would confirm that the attacker
has correctly guessed the username.</p>
</section>
<!-- /Security::cross-origin -->
</section>
<!-- /Security -->
<section>
<h2 id="acknowledgements">Acknowledgements</h2>
<p>Much of the content here is inspired heavily by Gervase
Markham’s <a href="http://www.gerv.net/security/link-fingerprints/">Link Fingerprints</a> concept, as well as WHATWG’s <a href="https://wiki.whatwg.org/wiki/Link_Hashes">Link Hashes</a>.</p>
<p>A special thanks to Mike West of Google, Inc. for his invaluable contributions
to the initial version of this spec. Additionally, Brad Hill, Anne van Kesteren,
Jonathan Kingston, Mark Nottingham, Dan Veditz, Eduardo Vela, Tanvi Vyas, and
Michal Zalewski provided invaluable feedback.</p>
</section>
</body>
</html>