Permalink
Browse files

Make the bikeshed spec the editors' draft

  • Loading branch information...
1 parent 42e2d03 commit 7c4a2de1013e2b812cdd70ae5217960cc102a530 @fmarier fmarier committed Jun 15, 2016
Showing with 3,150 additions and 3,150 deletions.
  1. +6 −6 Makefile
  2. +0 −2,426 index.bikeshed.html
  3. 0 index.bikeshed.bs → index.bs
  4. +2,320 −718 index.html
  5. +824 −0 index.kramdown.html
  6. 0 spec.markdown → spec_v1.markdown
View
@@ -1,13 +1,13 @@
-all: clean index.html index.bikeshed.html
+all: clean index.html index.kramdown.html
clean:
- rm -rf index.html index.bikeshed.html
+ rm -rf index.html index.kramdown.html
-index.html: spec.markdown template.erb
- sed -e 's/\[\[/\\[\\[/g' -e 's/\]\]/\\]\\]/g' ./spec.markdown | kramdown --parse-block-html --template='template.erb' > index.html
+index.kramdown.html: spec_v1.markdown template.erb
+ sed -e 's/\[\[/\\[\\[/g' -e 's/\]\]/\\]\\]/g' ./spec_v1.markdown | kramdown --parse-block-html --template='template.erb' > index.kramdown.html
-index.bikeshed.html: index.bikeshed.bs
- curl https://api.csswg.org/bikeshed/ -F file=@index.bikeshed.bs -F force=1 > ./index.bikeshed.html
+index.html: index.bs
+ curl https://api.csswg.org/bikeshed/ -F [email protected] -F force=1 > ./index.html
publish: all
git push origin master
View
0 additions, 2,426 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
File renamed without changes.
View
2,320 additions, 718 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
@@ -0,0 +1,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>&lt;script src="https://example.com/example-framework.js"
+ integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7"
+ crossorigin="anonymous"&gt;&lt;/script&gt;
+</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>&lt;link rel="stylesheet" href="https://site53.example.net/style.css"
+ integrity="sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB"
+ crossorigin="anonymous"&gt;
+</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>&lt;script src="https://analytics-r-us.example.com/v1.0/include.js"
+ integrity="sha384-MBO5IDfYaE6c6Aao94oZrIOiC6CGiSN2n4QUbHNPhzk5Xhm0djZLQqTpL0HzTUxk"
+ crossorigin="anonymous"&gt;&lt;/script&gt;
+</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>&lt;script src="hello_world.js"
+ integrity="sha384-dOTZf16X8p34q2/kYyEFm0jh89uTjikhnzjeLeF0FHsEaYKb1A1cv+Lyv4Hk8vHd
+ sha512-Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw=="
+ crossorigin="anonymous"&gt;&lt;/script&gt;
+</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>&lt;script src="https://example.com/example-framework.js"
+ integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7
+ sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB"
+ crossorigin="anonymous"&gt;&lt;/script&gt;
+</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 = &lt;hash-algo production from [Content Security Policy Level 2, section 4.2]&gt;
+base64-value = &lt;base64-value production from [Content Security Policy Level 2, section 4.2]&gt;
+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>
View
File renamed without changes.

0 comments on commit 7c4a2de

Please sign in to comment.