From fbf2055d5ffd308b9d9364709df5aad2320497e8 Mon Sep 17 00:00:00 2001 From: Joel Howard Willis Weinberger Date: Thu, 2 Apr 2015 14:12:46 -0700 Subject: [PATCH 1/6] Added note on content negotiation. --- specs/subresourceintegrity/index.html | 12 ++++++++++-- specs/subresourceintegrity/spec.markdown | 9 +++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/specs/subresourceintegrity/index.html b/specs/subresourceintegrity/index.html index abc28172..44bab0eb 100644 --- a/specs/subresourceintegrity/index.html +++ b/specs/subresourceintegrity/index.html @@ -147,7 +147,7 @@

Introduction

sha256-C6CB9UYIS9UJeqinPHWTHVqh/E1uhG5Twh+Y5qFQmYg="> -

Scripts, of course, are not the only resource type which would benefit +

Scripts, of course, are not the only resource type which would benefit from integrity validation. The scheme specified here applies to all HTML elements which trigger fetches, as well as to fetches triggered from CSS and JavaScript.

@@ -260,7 +260,7 @@

Key Concepts and Terminology

and format of that resource. [[!MIMETYPE]]

The message body and the transfer encoding of a resource -are defined by RFC7230, section 3. [[!RFC7230]]

+are defined by RFC7230, section 3. [[!RFC7230]]

The representation data and content encoding of a resource are defined by RFC7231, section 3. [[!RFC7231]]

@@ -690,6 +690,14 @@

The integrity attribute

The integrity IDL attribute must reflect the integrity content attribute.

+
+

It should be noted that this syntax does not allow for content negotiation if +the developer specifies a MIME type. A change to the syntax to allow this may be +considered in a future version of the spec, but for now, if a developer wants to +use content negotiation, they will have to omit an option-expression.

+ +
+ diff --git a/specs/subresourceintegrity/spec.markdown b/specs/subresourceintegrity/spec.markdown index 4bfad503..5a21cf9c 100755 --- a/specs/subresourceintegrity/spec.markdown +++ b/specs/subresourceintegrity/spec.markdown @@ -571,6 +571,15 @@ value must be a valid [MIME type][]. The `integrity` IDL attribute must [reflect][] the `integrity` content attribute. +
+It should be noted that this syntax does not allow for [content negotiation][] if +the developer specifies a MIME type. A change to the syntax to allow this may be +considered in a future version of the spec, but for now, if a developer wants to +use content negotiation, they will have to omit an `option-expression`. + +[content negotiation]: https://www.igvita.com/2013/05/01/deploying-webp-via-accept-content-negotiation/ +
+ [reflect]: http://www.w3.org/TR/html5/infrastructure.html#reflect From f6e9398fa769c7aee2ababc6f1bd4ba8f1f19260 Mon Sep 17 00:00:00 2001 From: Joel Howard Willis Weinberger Date: Thu, 2 Apr 2015 15:08:44 -0700 Subject: [PATCH 2/6] Specify that the omission will have to be a type option-expression. --- specs/subresourceintegrity/index.html | 2 +- specs/subresourceintegrity/spec.markdown | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/subresourceintegrity/index.html b/specs/subresourceintegrity/index.html index 44bab0eb..a2c15d47 100644 --- a/specs/subresourceintegrity/index.html +++ b/specs/subresourceintegrity/index.html @@ -694,7 +694,7 @@

The integrity attribute

It should be noted that this syntax does not allow for content negotiation if the developer specifies a MIME type. A change to the syntax to allow this may be considered in a future version of the spec, but for now, if a developer wants to -use content negotiation, they will have to omit an option-expression.

+use content negotiation, they will have to omit a type option-expression.

diff --git a/specs/subresourceintegrity/spec.markdown b/specs/subresourceintegrity/spec.markdown index 5a21cf9c..38a05e6c 100755 --- a/specs/subresourceintegrity/spec.markdown +++ b/specs/subresourceintegrity/spec.markdown @@ -575,7 +575,7 @@ The `integrity` IDL attribute must [reflect][] the `integrity` content attribute It should be noted that this syntax does not allow for [content negotiation][] if the developer specifies a MIME type. A change to the syntax to allow this may be considered in a future version of the spec, but for now, if a developer wants to -use content negotiation, they will have to omit an `option-expression`. +use content negotiation, they will have to omit a `type` `option-expression`. [content negotiation]: https://www.igvita.com/2013/05/01/deploying-webp-via-accept-content-negotiation/ From 54e31a12846eff424a018ce9d2078cfec798a888 Mon Sep 17 00:00:00 2001 From: Joel Howard Willis Weinberger Date: Wed, 8 Apr 2015 10:08:51 -0700 Subject: [PATCH 3/6] Changed integrity productions to reflect per-hash-expression options and to get rid of MIME type note. --- specs/subresourceintegrity/spec.markdown | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/specs/subresourceintegrity/spec.markdown b/specs/subresourceintegrity/spec.markdown index 38a05e6c..cf9b704c 100755 --- a/specs/subresourceintegrity/spec.markdown +++ b/specs/subresourceintegrity/spec.markdown @@ -556,8 +556,9 @@ The `integrity` attribute represents [integrity metadata][] 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: - integrity-metadata = *WSP [ option-expression *( 1*WSP option-expression ) 1*WSP ] hash-expression *( 1*WSP hash-expression ) *WSP / *WSP - option-expression = option-name ":" option-value + integrity-metadata = *WSP hash-with-options *( 1*WSP hash-with-options ) *WSP / *WSP + hash-with-options = hash-expression *("?" option-expression) + option-expression = option-name "=" option-value option-name = 1*option-name-char option-name-char = ALPHA / DIGIT / "-" option-value = *option-value-char @@ -566,18 +567,14 @@ valid metadata as described by the following ABNF grammar: base64-value = hash-expression = hash-algo "-" base64-value -At the moment, the only option-name that is defined is `type` and its -value must be a valid [MIME type][]. - The `integrity` IDL attribute must [reflect][] the `integrity` content attribute. -
-It should be noted that this syntax does not allow for [content negotiation][] if -the developer specifies a MIME type. A change to the syntax to allow this may be -considered in a future version of the spec, but for now, if a developer wants to -use content negotiation, they will have to omit a `type` `option-expression`. +`option-expression`s are associated on a per `hash-expression` basis and are +applied only to the `hash-expression` that immediately precedes it. -[content negotiation]: https://www.igvita.com/2013/05/01/deploying-webp-via-accept-content-negotiation/ +
+At the moment, no `option-expression`s are defined. However, future versions of +the spec make define options, such as [MIME types][].
[reflect]: http://www.w3.org/TR/html5/infrastructure.html#reflect From beec679207dbdd02231d6f7090833ecb2e1690cc Mon Sep 17 00:00:00 2001 From: Joel Howard Willis Weinberger Date: Wed, 8 Apr 2015 10:13:12 -0700 Subject: [PATCH 4/6] Got rid of MIME type references, other than note that they may be added in the future. --- specs/subresourceintegrity/spec.markdown | 43 +++++------------------- 1 file changed, 8 insertions(+), 35 deletions(-) diff --git a/specs/subresourceintegrity/spec.markdown b/specs/subresourceintegrity/spec.markdown index cf9b704c..255d4aaf 100755 --- a/specs/subresourceintegrity/spec.markdown +++ b/specs/subresourceintegrity/spec.markdown @@ -45,8 +45,7 @@ This example can be communicated to a user agent by adding the hash to a `script` element, like so: + integrity="sha256-SDfwewFAE...wefjijfE"> {:.example.highlight} * A user agent wishes to ensure that pieces of its UI which are rendered via @@ -154,9 +152,6 @@ is an origin whose scheme component is HTTPS. [potentially secure origin]: #dfn-potentially-secure-origin [mixedcontent]: https://www.w3.org/TR/mixed-content/#potentially-secure-origin -The MIME type of a resource is a technical hint about the use -and format of that resource. [[!MIMETYPE]] - The message body and the transfer encoding of a resource are defined by [RFC7230, section 3][messagebody]. [[!RFC7230]] @@ -200,11 +195,9 @@ metadata, which consists of the following pieces of information: * cryptographic hash function ("alg") * [digest][] ("val") -* the resource's [MIME type][] ("type") The hash function and digest MUST be provided in order to validate a -resource's integrity. The MIME type SHOULD be provided, as it mitigates the -risk of certain attack vectors. +resource's integrity. This metadata MUST be encoded in the same format as the `hash-source` in [section 4.2 of the Content Security Policy Level 2 specification][csp2-section42]. @@ -217,11 +210,6 @@ digest that results. This can be encoded as follows: sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng= {:.example.highlight} -Or, if the author further wishes to specify the Content Type (`application/javascript`): - - type:application/javascript sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng= -{:.example.highlight} -
Digests may be generated using any number of utilities. [OpenSSL][], for example, is quite commonly available. The example in this section is the @@ -235,7 +223,6 @@ result of the following command line: [sha2]: #dfn-sha-2 [digest]: #dfn-digest -[MIME type]: #dfn-mime-type [integrity metadata]: #dfn-integrity-metadata @@ -261,9 +248,8 @@ either of the following hash expressions: Authors may choose to specify both, for example: In this case, the user agent will choose the strongest hash function in the @@ -442,21 +428,11 @@ the user agent. metadata. 7. Let expectedValue be the val component of metadata. -8. Let expectedType be the type component of - metadata. -9. If expectedType is not the empty string, and is not a - case-insensitive match for resource's [MIME type][], - return `false`. -10. Let actualValue be the result of [applying +8. Let actualValue be the result of [applying algorithm to resource][apply-algorithm]. -11. If actualValue is a case-sensitive match for +9. If actualValue is a case-sensitive match for expectedValue, return `true`. Otherwise, return `false`. -If expectedType is the empty string in #10, it would -be reasonable for the user agent to warn the page's author about the -dangers of MIME type confusion attacks via its developer console. -{:.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 @@ -494,9 +470,6 @@ to enable the rest of this specification's work [[!FETCH]]: 1. Set response's integrity state to `pending`. 2. Include a `Cache-Control` header whose value is "no-transform". - 3. If request's integrity metadata contains a Content Type: - 1. Set request's `Accept` header value to the value - of request's integrity metadata's Content Type. 4. Add the following step before step #1 of the handling of 401 status codes in the [HTTP fetch][] algorithm: From 7b00748ea09ca291215c8802a296ccda6c226d43 Mon Sep 17 00:00:00 2001 From: Joel Howard Willis Weinberger Date: Wed, 8 Apr 2015 11:29:50 -0700 Subject: [PATCH 5/6] Modified metadata algorithm to generate a set of strong hashes. --- specs/subresourceintegrity/index.html | 115 ++++++++++------------- specs/subresourceintegrity/spec.markdown | 65 ++++++++----- 2 files changed, 93 insertions(+), 87 deletions(-) diff --git a/specs/subresourceintegrity/index.html b/specs/subresourceintegrity/index.html index a2c15d47..6896bd0c 100644 --- a/specs/subresourceintegrity/index.html +++ b/specs/subresourceintegrity/index.html @@ -143,8 +143,7 @@

Introduction

script element, like so:

<script src="https://code.jquery.com/jquery-1.10.2.min.js"
-        integrity="type:application/javascript
-                   sha256-C6CB9UYIS9UJeqinPHWTHVqh/E1uhG5Twh+Y5qFQmYg=">
+        integrity="sha256-C6CB9UYIS9UJeqinPHWTHVqh/E1uhG5Twh+Y5qFQmYg=">
 

Scripts, of course, are not the only resource type which would benefit @@ -192,7 +191,7 @@

Resource Integrity

integrity metadata to the link element included on her page:

<link rel="stylesheet" href="https://site53.cdn.net/style.css"
-      integrity="type:text/css sha256-SDfwewFAE...wefjijfE">
+      integrity="sha256-SDfwewFAE...wefjijfE">
 
  • @@ -203,8 +202,7 @@

    Resource Integrity

    adding it to the script element she includes on her page:

    <script src="https://analytics-r-us.com/v1.0/include.js"
    -        integrity="type:application/javascript
    -                   sha256-SDfwewFAE...wefjijfE"></script>
    +        integrity="sha256-SDfwewFAE...wefjijfE"></script>
     
  • @@ -256,9 +254,6 @@

    Key Concepts and Terminology

    Content specification. An example of a potentially secure origin is an origin whose scheme component is HTTPS.

    -

    The MIME type of a resource is a technical hint about the use -and format of that resource. [[!MIMETYPE]]

    -

    The message body and the transfer encoding of a resource are defined by RFC7230, section 3. [[!RFC7230]]

    @@ -295,12 +290,10 @@

    Integrity metadata

    • cryptographic hash function (“alg”)
    • digest (“val”)
    • -
    • the resource’s MIME type (“type”)

    The hash function and digest MUST be provided in order to validate a -resource’s integrity. The MIME type SHOULD be provided, as it mitigates the -risk of certain attack vectors.

    +resource’s integrity.

    This metadata MUST be encoded in the same format as the hash-source in section 4.2 of the Content Security Policy Level 2 specification.

    @@ -313,11 +306,6 @@

    Integrity metadata

    sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=
     
    -

    Or, if the author further wishes to specify the Content Type (application/javascript):

    - -
    type:application/javascript sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=
    -
    -

    Digests may be generated using any number of utilities. OpenSSL, for example, is quite commonly available. The example in this section is the @@ -353,9 +341,8 @@

    Agility

    Authors may choose to specify both, for example:

    <script src="hello_world.js"
    -   integrity="type:application/javascript
    -      sha256-+MO/YqmqPm/BYZwlDkir51GTc9Pt9BvmLrXcRRma8u8=
    -      sha512-rQw3wx1psxXzqB8TyM3nAQlK2RcluhsNwxmcqXE2YbgoDW735o8TPmIR4uWpoxUERddvFwjgRSGw7gNPCwuvJg==
    +   integrity="sha256-+MO/YqmqPm/BYZwlDkir51GTc9Pt9BvmLrXcRRma8u8=
    +              sha512-rQw3wx1psxXzqB8TyM3nAQlK2RcluhsNwxmcqXE2YbgoDW735o8TPmIR4uWpoxUERddvFwjgRSGw7gNPCwuvJg==
         "></script>
     
    @@ -379,15 +366,14 @@

    Agility

    Priority

    -

    User agents MUST provide a mechanism of determining the relative priority of -two hash functions. That is, if a user agent implemented a function like -getPrioritizedHashFunction(a, b) it would return the hash function -the user agent considers the most collision-resistant. -For example, getPrioritizedHashFunction('SHA-256', 'SHA-512') would return -SHA-512.

    +

    User agents MUST provide a mechanism of 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 getPrioritizedHashFunction(a, +b) it would return the hash function the user agent considers the most +collision-resistant. For example, getPrioritizedHashFunction('SHA-256', +'SHA-512') would return SHA-512 and getPrioritizedHashFunction('SHA-256', +'SHA-256') would return the empty string.

    -

    If both algorithms are equally strong, the user agent SHOULD ensure that there -is a consistent ordering.

    @@ -510,22 +496,25 @@

    Parse metadata.

    Get the strongest metadata from set.

      -
    1. Let strongest be the empty string.
    2. +
    3. Let result be the empty set and strongest be the empty +string.
    4. For each item in set:
        -
      1. If strongest is the empty string, set strongest -to item, skip to the next -item.
      2. +
      3. If result is the empty set, add item to +result and set strongest to item, skip +to the next item.
      4. Let currentAlgorithm be the alg component of strongest.
      5. Let newAlgorithm be the alg component of item.
      6. If the result of getPrioritizedHashFunction(currentAlgorithm, newAlgorithm) -is newAlgorithm, set strongest to -item.
      7. +is the empty string, add item to result. If the +result is newAlgorithm, set strongest to +item, set result to the empty set, and add +item to result.
    5. -
    6. Return strongest.
    7. +
    8. Return result.
    @@ -542,24 +531,32 @@

    Does resource m
  • If parsedMetadata is no metadata, return true.
  • Let metadata be the result of getting the strongest metadata from parsedMetadata.
  • -
  • Let algorithm be the alg component of -metadata.
  • -
  • Let expectedValue be the val component of +
  • For each item in metadata: +
      +
    1. Let algorithm be the alg component of metadata.
    2. -
    3. Let expectedType be the type component of +
    4. Let expectedValue be the val component of metadata.
    5. -
    6. If expectedType is not the empty string, and is not a -case-insensitive match for resource’s MIME type, -return false.
    7. -
    8. Let actualValue be the result of applying +
    9. Let actualValue be the result of applying algorithm to resource.
    10. -
    11. If actualValue is a case-sensitive match for -expectedValue, return true. Otherwise, return false.
    12. +
    13. If actualValue is a case-sensitive match for +expectedValue, return true.
    14. +
    +
  • +
  • Return false.
  • -

    If expectedType is the empty string in #10, it would -be reasonable for the user agent to warn the page’s author about the -dangers of MIME type confusion attacks via its developer console.

    +

    This algorithm allows the user agent to accept multiple, valid strong hash +functions. For example, a developer might write a script element such as:

    + +
    <script src="https://foobar.com/content-changes.js"
    +        integrity="sha256-C6CB9UYIS9UJeqinPHWTHVqh/E1uhG5Twh+Y5qFQmYg=
    +                   sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=">
    +
    + +

    which would allow the user agent to accept two different content payloads, one +of which matches the first SHA256 hash value and the other matches the second +SHA256 hash value.

    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 @@ -603,12 +600,6 @@

    Modifications to Fetch

    1. Set response’s integrity state to pending.
    2. Include a Cache-Control header whose value is “no-transform”.
    3. -
    4. If request’s integrity metadata contains a Content Type: -
        -
      1. Set request’s Accept header value to the value -of request’s integrity metadata’s Content Type.
      2. -
      -
  • @@ -674,8 +665,9 @@

    The integrity attribute

    The value of the attribute MUST be either the empty string, or at least one valid metadata as described by the following ABNF grammar:

    -
    integrity-metadata = *WSP [ option-expression *( 1*WSP option-expression ) 1*WSP ] hash-expression *( 1*WSP hash-expression ) *WSP / *WSP
    -option-expression  = option-name ":" option-value
    +    
    integrity-metadata = *WSP hash-with-options *( 1*WSP hash-with-options ) *WSP / *WSP
    +hash-with-options  = hash-expression *("?" option-expression)
    +option-expression  = option-name "=" option-value
     option-name        = 1*option-name-char
     option-name-char   = ALPHA / DIGIT / "-"
     option-value       = *option-value-char
    @@ -685,17 +677,14 @@ 

    The integrity attribute

    hash-expression = hash-algo "-" base64-value
    -

    At the moment, the only option-name that is defined is type and its -value must be a valid MIME type.

    -

    The integrity IDL attribute must reflect the integrity content attribute.

    -
    -

    It should be noted that this syntax does not allow for content negotiation if -the developer specifies a MIME type. A change to the syntax to allow this may be -considered in a future version of the spec, but for now, if a developer wants to -use content negotiation, they will have to omit a type option-expression.

    +

    option-expressions are associated on a per hash-expression basis and are +applied only to the hash-expression that immediately precedes it.

    +
    +

    At the moment, no option-expressions are defined. However, future versions of +the spec make define options, such as [MIME types][].

    diff --git a/specs/subresourceintegrity/spec.markdown b/specs/subresourceintegrity/spec.markdown index 255d4aaf..f679c8cf 100755 --- a/specs/subresourceintegrity/spec.markdown +++ b/specs/subresourceintegrity/spec.markdown @@ -271,15 +271,14 @@ stronger hash functions as they become available.
    #### Priority -User agents MUST provide a mechanism of determining the relative priority of -two hash functions. That is, if a user agent implemented a function like -getPrioritizedHashFunction(a, b) it would return the hash function -the user agent considers the most collision-resistant. -For example, `getPrioritizedHashFunction('SHA-256', 'SHA-512')` would return -`SHA-512`. - -If both algorithms are equally strong, the user agent SHOULD ensure that there -is a consistent ordering. +User agents MUST provide a mechanism of 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 getPrioritizedHashFunction(a, +b) it would return the hash function the user agent considers the most +collision-resistant. For example, `getPrioritizedHashFunction('SHA-256', +'SHA-512')` would return `SHA-512` and `getPrioritizedHashFunction('SHA-256', +'SHA-256')` would return the empty string. +
    @@ -397,19 +396,22 @@ the user agent.
    #### Get the strongest metadata from set. -1. Let strongest be the empty string. +1. Let result be the empty set and strongest be the empty + string. 2. For each item in set: - 1. If strongest is the empty string, set strongest - to item, skip to the next - item. + 1. If result is the empty set, add item to + result and set strongest to item, skip + to the next item. 2. Let currentAlgorithm be the alg component of strongest. 3. Let newAlgorithm be the alg component of item. 4. If the result of [`getPrioritizedHashFunction(currentAlgorithm, newAlgorithm)`][getPrioritizedHashFunction] - is newAlgorithm, set strongest to - item. -3. Return strongest. + is the empty string, add item to result. If the + result is newAlgorithm, set strongest to + item, set result to the empty set, and add + item to result. +3. Return result. [getPrioritizedHashFunction]: #dfn-getprioritizedhashfunction-a-b
    @@ -424,14 +426,29 @@ the user agent. 4. If parsedMetadata is `no metadata`, return `true`. 5. Let metadata be the result of [getting the strongest metadata from parsedMetadata][get-the-strongest]. -6. Let algorithm be the alg component of - metadata. -7. Let expectedValue be the val component of - metadata. -8. Let actualValue be the result of [applying - algorithm to resource][apply-algorithm]. -9. If actualValue is a case-sensitive match for - expectedValue, return `true`. Otherwise, return `false`. +6. For each item in metadata: + 1. Let algorithm be the alg component of + metadata. + 2. Let expectedValue be the val component of + metadata. + 3. Let actualValue be the result of [applying + algorithm to resource][apply-algorithm]. + 4. If actualValue is a case-sensitive match for + expectedValue, return `true`. +7. Return `false`. + +This algorithm allows the user agent to accept multiple, valid strong hash +functions. For example, a developer might write a `script` element such as: + +