From 14579844eb5e1150f566ffee3de50de2b4b781df Mon Sep 17 00:00:00 2001 From: Mike West Date: Tue, 14 Oct 2025 10:00:41 +0000 Subject: [PATCH 1/2] Handle `Unencoded-Digest` assertions. Signature-based Integrity [1] relies on user agents properly handling `Unencoded-Digest` headers [2] which deliver a server's assertions about the integrity of a given response's body. This patch extracts the relevant algorithms from [1], spelling out the processing model for the header, and verifying response integrity at the end of Main Fetch, alongside SRI's existing check. This is one step of the Signature-based Integrity upstreaming work detailed in [3]. [1]: https://wicg.github.io/signature-based-sri/ [2]: https://httpwg.org/http-extensions/draft-ietf-httpbis-unencoded-digest.html [3]: https://github.com/WICG/signature-based-sri/issues/49. --- fetch.bs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/fetch.bs b/fetch.bs index 8d19ae84d..bc1f2c9d1 100755 --- a/fetch.bs +++ b/fetch.bs @@ -22,6 +22,8 @@ urlPrefix:https://httpwg.org/specs/rfc9651.html#;type:dfn;spec:rfc9651 url:text-parse;text:parsing structured fields url:;text:structured header url:token;text:structured field token + url:binary;text:structured field byte sequence + url:dictionary;text:structured field dictionary urlPrefix:https://httpwg.org/specs/rfc9110.html#;type:dfn;spec:http url:method.overview;text:method @@ -66,6 +68,10 @@ urlPrefix:https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-layered-cooki url:name-retrieve-cookies;text:retrieve cookies url:name-serialize-cookies;text:serialize cookies url:name-garbage-collect-cookies;text:garbage collect cookies + +urlPrefix:https://httpwg.org/http-extensions/draft-ietf-httpbis-unencoded-digest.html#;spec:unencoded-digest + type:http-header + url:name-the-unencoded-digest-field;text:unencoded-digest
@@ -117,6 +123,11 @@ urlPrefix:https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-layered-cooki
         "href": "https://www.kb.cert.org/vuls/id/150227",
         "title": "HTTP proxy default configurations allow arbitrary TCP connections."
     },
+    "UNENCODED-DIGEST": {
+        "authors": ["Lucas Pardue", "Mike West"],
+        "href": "https://httpwg.org/http-extensions/draft-ietf-httpbis-unencoded-digest.html",
+        "title": "HTTP Unencoded Digest"
+    },
     "WEBTRANSPORT-HTTP3": {
         "authors": ["V. Vasiliev"],
         "href": "https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3",
@@ -4483,6 +4494,72 @@ indicates the request’s purpose is to fetch a resource that is anticipated to
 prefetch, or to treat it differently when counting page visits.
 
 
+

`Unencoded-Digest` header

+ +

The `Unencoded-Digest` header field represents a server's +assertions about the integrity of a response's content. It is a structured header whose value +must be a dictionary whose keys specify hashing +algorithms, and whose values are byte sequences +represent a digest of the response produced via the specified algorithm. [[!UNENCODED-DIGEST]] + + +

+

To verify `Unencoded-Digest` assertions, given a +byte sequence bytes and a header list list, run these +steps: + +

    +
  1. Let header be the result of + getting the + `Unencoded-Digest` header as a "dictionary" from + list. + +

  2. If header is null, then return verified. + +

  3. +

    For each algdigest of header: + +

      +
    1. +

      Switch on alg: + +

      +
      "sha-256" +
      +
        +
      1. Let body digest be the result of executing the SHA-256 algorithm on + bytes. [[!FIPS-180-4]] + +

      2. If body digest matches digest, continue. +

      + +
      "sha-512" +
      +
        +
      1. Let body digest be the result of executing the SHA-512 algorithm on + bytes. [[!FIPS-180-4]] + +

      2. If body digest matches digest, continue. +

      + +
      Otherwise: +

      Continue. +

      + +
    2. Return failed. +

    + +
  4. Return verified. +

+ +

This algorithm requires all valid digests delivered via +`Unencoded-Digest` to match the response’s decoded body, while +ignoring unknown algorithms. Since the server controls both the body and the headers, it seems +unnecessary to allow the flexibility of allowing the asserted digests to match more than one +resource (as we do in client-initiated checks via [[SRI]], which need to support servers' +content negotiation). +

+

Fetching

@@ -5022,7 +5099,9 @@ steps:

This standardizes the error handling for servers that violate HTTP.

  • -

    If request's integrity metadata is not the empty string, then: +

    If request's integrity metadata is not the empty string, or if + internalResponse's header list contains + `Unencoded-Digest`, then:

    1. Let processBodyError be this step: run fetch response handover given @@ -5035,6 +5114,10 @@ steps:

      Let processBody given bytes be these steps:

        +
      1. Verify `Unencoded-Digest` assertions given bytes and + internalResponse's header list. If the result is not + verified, then run processBodyError and abort these steps. +

      2. If bytes do not match request's integrity metadata, then run processBodyError and abort these steps. [[!SRI]] From 0b03af397017ffef2a196ba0f2410e5e7489095e Mon Sep 17 00:00:00 2001 From: Mike West Date: Tue, 14 Oct 2025 10:47:37 +0000 Subject: [PATCH 2/2] fixup typo in a switch --- fetch.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fetch.bs b/fetch.bs index bc1f2c9d1..d6c1d7372 100755 --- a/fetch.bs +++ b/fetch.bs @@ -4542,8 +4542,8 @@ steps:

      3. If body digest matches digest, continue.

      -
      Otherwise: -

      Continue. +

      Otherwise +

      Continue.

    2. Return failed.