< draft-yasskin-wpack-bundled-exchanges-00.txt   draft-yasskin-wpack-bundled-exchanges-01.txt >
Network Working Group J. Yasskin Network Working Group J. Yasskin
Internet-Draft Google Internet-Draft Google
Intended status: Standards Track June 13, 2018 Intended status: Standards Track July 08, 2019
Expires: December 15, 2018 Expires: January 9, 2020
Bundled HTTP Exchanges Bundled HTTP Exchanges
draft-yasskin-wpack-bundled-exchanges-00 draft-yasskin-wpack-bundled-exchanges-01
Abstract Abstract
Bundled exchanges provide a way to bundle up groups of HTTP Bundled exchanges provide a way to bundle up groups of HTTP
request+response pairs to transmit or store them together. They can request+response pairs to transmit or store them together. They can
include multiple top-level resources with one identified as the include multiple top-level resources with one identified as the
default by a manifest, provide random access to their component default by a manifest, provide random access to their component
exchanges, and efficiently store 8-bit resources. exchanges, and efficiently store 8-bit resources.
Note to Readers Note to Readers
Discussion of this draft takes place on the ART area mailing list Discussion of this draft takes place on the wpack mailing list
(art@ietf.org), which is archived at (wpack@ietf.org), which is archived at
https://mailarchive.ietf.org/arch/search/?email_list=art [1]. https://www.ietf.org/mailman/listinfo/wpack [1].
The source code and issues list for this draft can be found in The source code and issues list for this draft can be found in
https://github.com/WICG/webpackage [2]. https://github.com/WICG/webpackage [2].
Status of This Memo Status of This Memo
This Internet-Draft is submitted in full conformance with the This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79. provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet- working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/. Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
This Internet-Draft will expire on December 15, 2018. This Internet-Draft will expire on January 9, 2020.
Copyright Notice Copyright Notice
Copyright (c) 2018 IETF Trust and the persons identified as the Copyright (c) 2019 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents Provisions Relating to IETF Documents
(https://trustee.ietf.org/license-info) in effect on the date of (https://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect carefully, as they describe your rights and restrictions with respect
to this document. Code Components extracted from this document must to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as the Trust Legal Provisions and are provided without warranty as
skipping to change at page 2, line 25 skipping to change at page 2, line 25
Table of Contents Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3 1.1. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3
1.2. Mode of specification . . . . . . . . . . . . . . . . . . 3 1.2. Mode of specification . . . . . . . . . . . . . . . . . . 3
2. Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2. Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1. Stream attributes and operations . . . . . . . . . . . . 4 2.1. Stream attributes and operations . . . . . . . . . . . . 4
2.2. Load a bundle's metadata . . . . . . . . . . . . . . . . 4 2.2. Load a bundle's metadata . . . . . . . . . . . . . . . . 4
2.2.1. Load a bundle's metadata from the end . . . . . . . . 5 2.2.1. Load a bundle's metadata from the end . . . . . . . . 5
2.3. Load a response from a bundle . . . . . . . . . . . . . . 5 2.3. Load a response from a bundle . . . . . . . . . . . . . . 5
3. Format . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3. Format . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.1. Top-level structure . . . . . . . . . . . . . . . . . . . 5 3.1. Top-level structure . . . . . . . . . . . . . . . . . . . 6
3.2. Load a bundle's metadata . . . . . . . . . . . . . . . . 6 3.2. Serving constraints . . . . . . . . . . . . . . . . . . . 7
3.2.1. Parsing the index section . . . . . . . . . . . . . . 8 3.3. Load a bundle's metadata . . . . . . . . . . . . . . . . 7
3.2.2. Parsing the manifest section . . . . . . . . . . . . 9 3.3.1. Parsing the index section . . . . . . . . . . . . . . 10
3.2.3. Parsing the critical section . . . . . . . . . . . . 10 3.3.2. Parsing the manifest section . . . . . . . . . . . . 13
3.2.4. The responses section . . . . . . . . . . . . . . . . 10 3.3.3. Parsing the signatures section . . . . . . . . . . . 14
3.2.5. Starting from the end . . . . . . . . . . . . . . . . 10 3.3.4. Parsing the critical section . . . . . . . . . . . . 15
3.3. Load a response from a bundle . . . . . . . . . . . . . . 11 3.3.5. The responses section . . . . . . . . . . . . . . . . 16
3.4. Parsing CBOR items . . . . . . . . . . . . . . . . . . . 13 3.3.6. Starting from the end . . . . . . . . . . . . . . . . 16
3.4.1. Parse a known-length item . . . . . . . . . . . . . . 13 3.4. Load a response from a bundle . . . . . . . . . . . . . . 17
3.4.2. Parsing variable-length data from a bytestring . . . 13 3.5. Parsing CBOR items . . . . . . . . . . . . . . . . . . . 19
3.5. Interpreting CBOR HTTP headers . . . . . . . . . . . . . 14 3.5.1. Parse a known-length item . . . . . . . . . . . . . . 19
4. Guidelines for bundle authors . . . . . . . . . . . . . . . . 15 3.5.2. Parsing variable-length data from a bytestring . . . 19
5. Security Considerations . . . . . . . . . . . . . . . . . . . 15 3.5.3. Parsing the type and argument of a CBOR item . . . . 20
6. IANA considerations . . . . . . . . . . . . . . . . . . . . . 16 3.6. Interpreting CBOR HTTP headers . . . . . . . . . . . . . 20
6.1. Internet Media Type Registration . . . . . . . . . . . . 16 4. Guidelines for bundle authors . . . . . . . . . . . . . . . . 21
6.2. Web Bundle Section Name Registry . . . . . . . . . . . . 17 5. Security Considerations . . . . . . . . . . . . . . . . . . . 22
7. References . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.1. Version skew . . . . . . . . . . . . . . . . . . . . . . 22
7.1. Normative References . . . . . . . . . . . . . . . . . . 17 5.2. Content sniffing . . . . . . . . . . . . . . . . . . . . 22
7.2. Informative References . . . . . . . . . . . . . . . . . 19 6. IANA considerations . . . . . . . . . . . . . . . . . . . . . 23
7.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 19 6.1. Internet Media Type Registration . . . . . . . . . . . . 23
Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . 19 6.2. Web Bundle Section Name Registry . . . . . . . . . . . . 24
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 19 7. References . . . . . . . . . . . . . . . . . . . . . . . . . 25
7.1. Normative References . . . . . . . . . . . . . . . . . . 25
7.2. Informative References . . . . . . . . . . . . . . . . . 27
7.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Appendix A. Change Log . . . . . . . . . . . . . . . . . . . . . 27
Appendix B. Acknowledgements . . . . . . . . . . . . . . . . . . 28
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 28
1. Introduction 1. Introduction
To satisfy the use cases in [I-D.yasskin-webpackage-use-cases], this To satisfy the use cases in [I-D.yasskin-webpackage-use-cases], this
document proposes a new bundling format to group HTTP resources. document proposes a new bundling format to group HTTP resources.
Several of the use cases require the resources to be signed: that's Several of the use cases require the resources to be signed: that's
provided by bundling signed exchanges provided by bundling signed exchanges
([I-D.yasskin-http-origin-signed-responses]) rather than natively in ([I-D.yasskin-http-origin-signed-responses]) rather than natively in
this format. this format.
skipping to change at page 4, line 6 skipping to change at page 4, line 10
network stream. network stream.
A bundle is parsed from a stream of bytes, which is assumed to have A bundle is parsed from a stream of bytes, which is assumed to have
the attributes and operations described in Section 2.1. the attributes and operations described in Section 2.1.
Bundle parsers support two operations, Load a bundle's metadata Bundle parsers support two operations, Load a bundle's metadata
(Section 2.2) and Load a response from a bundle (Section 2.3) each of (Section 2.2) and Load a response from a bundle (Section 2.3) each of
which can return an error instead of their normal result. which can return an error instead of their normal result.
A client is expected to load the metadata for a bundle as soon as it A client is expected to load the metadata for a bundle as soon as it
start downloading it or otherwise discovers it. Then, when fetching starts downloading it or otherwise discovers it. Then, when fetching
([FETCH]) a request, the cliend is expected to match it against the ([FETCH]) a request, the client is expected to match it against the
requests in the metadata, and if one matches, load that request's requests in the metadata, and if one matches, load that request's
response. response.
2.1. Stream attributes and operations 2.1. Stream attributes and operations
o A sequence of *available bytes*. As the stream delivers bytes, o A sequence of *available bytes*. As the stream delivers bytes,
these are appended to the available bytes. these are appended to the available bytes.
o An *EOF* flag that's true if the available bytes include the o An *EOF* flag that's true if the available bytes include the
entire stream. entire stream.
skipping to change at page 4, line 36 skipping to change at page 4, line 40
fails. fails.
o A *read N bytes* operation, which blocks until N bytes are o A *read N bytes* operation, which blocks until N bytes are
available past the current offset, and then returns them and seeks available past the current offset, and then returns them and seeks
forward by N bytes. If the stream ends before enough bytes are forward by N bytes. If the stream ends before enough bytes are
received, either due to a network error or because the stream has received, either due to a network error or because the stream has
a finite length, the read operation returns an error instead. a finite length, the read operation returns an error instead.
2.2. Load a bundle's metadata 2.2. Load a bundle's metadata
This takes the bundle's stream and returns a map ([INFRA]) of This takes the bundle's stream and returns either an error (where an
metadata containing at least keys named: error is a "format error" or a "version error"), an error with a
fallback URL (which is also the primaryUrl when the bundle parses
successfully), or a map ([INFRA]) of metadata containing at least
keys named:
requests A map ([INFRA]) whose keys are [FETCH] requests for the primaryUrl The URL of the main resource in the bundle. If the
HTTP exchanges in the bundle, and whose values are opaque metadata client can't process the bundle for any reason, this is also the
that Load a response from a bundle can use to find the matching fallback URL, a reasonable URL to try to load instead.
response.
requests A map ([INFRA]) whose keys are URLs and whose values
consist of either:
* A single "ResponseMetadata" value for a non-content-negotiated
resource or
* A set of content-negotiated resources represented by
+ A "Variants" header field value
([I-D.ietf-httpbis-variants]) and
+ A map ([INFRA]) from each of the possible combinations of
one available-value for each variant-axis to a
"ResponseMetadata" structure. Load a response from a bundle
can use the "ResponseMetadata" structures to find the
matching response.
manifest The URL of the bundle's manifest(s). This is a URL to manifest The URL of the bundle's manifest(s). This is a URL to
support bundles with multiple different manifests, where the support bundles with multiple different manifests, where the
client uses content negotiation to select the most appropriate client uses content negotiation to select the most appropriate
one. one.
The map may include other items added by sections defined in the The map may include other items added by sections defined in the
Web Bundle Section Name Registry. Web Bundle Section Name Registry.
This operation only waits for a prefix of the stream that, if the This operation only waits for a prefix of the stream that, if the
bundle is encoded with the "responses" section last, ends before the bundle is encoded with the "responses" section last, ends before the
first response. first response.
This operation's implementation is in Section 3.2. This operation's implementation is in Section 3.3.
2.2.1. Load a bundle's metadata from the end 2.2.1. Load a bundle's metadata from the end
If a bundle's bytes are embedded in a longer sequence rather than If a bundle's bytes are embedded in a longer sequence rather than
being streamed, a parser can also load them starting from a pointer being streamed, a parser can also load them starting from a pointer
to the last byte of the bundle. This returns the same data as to the last byte of the bundle. This returns the same data as
Section 2.2. Section 2.2.
This operation's implementation is in Section 3.2.5. This operation's implementation is in Section 3.3.6.
2.3. Load a response from a bundle 2.3. Load a response from a bundle
This takes the sequence of bytes representing the bundle and one This takes the stream of bytes representing the bundle, a request
request returned from Section 2.2 with its metadata, and returns the ([FETCH]), and the "ResponseMetadata" returned from Section 2.2 for
response ([FETCH]) matching that request. the appropriate content-negotiated resource within the request's URL,
and returns the response ([FETCH]) matching that request.
This operation can be completed without inspecting bytes other than This operation can be completed without inspecting bytes other than
those that make up the loaded response, although higher-level those that make up the loaded response, although higher-level
operations like proving that an exchange is correctly signed operations like proving that an exchange is correctly signed
([I-D.yasskin-http-origin-signed-responses]) may need to load other ([I-D.yasskin-http-origin-signed-responses]) may need to load other
responses. responses.
Note that this operation uses the metadata for a particular request A client will generally want to load the response for a request that
returned by Section 2.2, while a client will generally want to load the client generated. For a URL with multiple variants, the client
the response for a request that the client generated. TODO: Specify SHOULD use the algorithm in Section 4 of [I-D.ietf-httpbis-variants]
how a client determines the best available bundled response, if any, to select the best variant.
for that client-generated request, in this or another document.
This operation's implementation is in Section 3.3. This operation's implementation is in Section 3.4.
3. Format 3. Format
3.1. Top-level structure 3.1. Top-level structure
_This section is non-normative._ _This section is non-normative._
A bundle holds a series of named sections. The beginning of the A bundle holds a series of named sections. The beginning of the
bundle maps section names to the range of bytes holding that section. bundle maps section names to the range of bytes holding that section.
The most important section is the "index" (Section 3.2.1), which The most important section is the "index" (Section 3.3.1), which
similarly maps serialized HTTP requests to the range of bytes holding similarly maps serialized HTTP requests to the range of bytes holding
that request's serialized response. Byte ranges are represented that request's serialized response. Byte ranges are represented
using an offset from some point in the bundle _after_ the encoding of using an offset from some point in the bundle _after_ the encoding of
the range itself, to reduce the amount of work needed to use the the range itself, to reduce the amount of work needed to use the
shortest possible encoding of the range. shortest possible encoding of the range.
Future specifications can define new sections with extra data, and if Future specifications can define new sections with extra data, and if
necessary, these sections can be marked "critical" (Section 3.2.3) to necessary, these sections can be marked "critical" (Section 3.3.4) to
prevent older parsers from using the rest of the bundle incorrectly. prevent older parsers from using the rest of the bundle incorrectly.
The bundle is roughly a CBOR item ([I-D.ietf-cbor-7049bis]) with the The bundle is a CBOR item ([CBORbis]) with the following CDDL
following CDDL ([I-D.ietf-cbor-cddl]) schema, but bundle parsers are ([CDDL]) schema:
required to successfully parse some byte strings that aren't valid
CBOR. For example, sections might have padding between them, or even
overlap, as long as the embedded relative offsets cause the parsing
algorithms in this specification to return data.
webbundle = [ webbundle = [
; &#127760;&#128230; in UTF-8. ; &#127760;&#128230; in UTF-8.
magic: h'F0 9F 8C 90 F0 9F 93 A6', magic: h'F0 9F 8C 90 F0 9F 93 A6',
section-offsets: bytes .cbor {* ($section-name .within tstr) => version: bytes .size 4,
[ offset: uint, length: uint] }, primary-url: whatwg-url,
sections: [* $section ], section-lengths: bytes .cbor [* (section-name: tstr, length: uint) ],
length: bytes .size 8, ; Big-endian number of bytes in the bundle. sections: [* any ],
] length: bytes .size 8, ; Big-endian number of bytes in the bundle.
]
$section-name /= "index" / "manifest" / "critical" / "responses" $section-name /= "index" / "manifest" / "signatures" / "critical" / "responses"
$section /= index / manifest / critical / responses $section /= index / manifest / signatures / critical / responses
responses = [*response] responses = [*response]
3.2. Load a bundle's metadata whatwg-url = tstr
A bundle holds a series of sections, which can be accessed randomly 3.2. Serving constraints
using the information in the "section-offset" CBOR item:
section-offsets = {* tstr => [ offset: uint, length: uint] }, When served over HTTP, a response containing an "application/
webbundle" payload MUST include at least the following response
header fields, to reduce content sniffing vulnerabilities
(Section 5.2):
Offsets in this item are relative to the _end_ of the section-offset o Content-Type: application/webbundle
item.
o X-Content-Type-Options: nosniff
3.3. Load a bundle's metadata
A bundle holds a series of sections, which can be accessed randomly
using the information in the "section-lengths" CBOR item, which holds
a list of alternating section names and section lengths:
section-lengths = [* (section-name: tstr, length: uint) ],
To implement Section 2.2, the parser MUST run the following steps, To implement Section 2.2, the parser MUST run the following steps,
taking the "stream" as input. taking the "stream" as input.
1. Seek to offset 0 in "stream". Assert: this operation doesn't 1. Seek to offset 0 in "stream". Assert: this operation doesn't
fail. fail.
2. If reading 10 bytes from "stream" returns an error or doesn't 2. If reading 10 bytes from "stream" returns an error or doesn't
return the bytes with hex encoding "84 48 F0 9F 8C 90 F0 9F 93 return the bytes with hex encoding "84 48 F0 9F 8C 90 F0 9F 93
A6" (the CBOR encoding of the 4-item array initial byte and A6" (the CBOR encoding of the 4-item array initial byte and
8-byte bytestring initial byte, followed by &#127760;&#128230; 8-byte bytestring initial byte, followed by &#127760;&#128230;
in UTF-8), return an error. in UTF-8), return a "format error".
3. Let "sectionOffsetsLength" be the result of getting the length 3. Let "version" be the result of reading 5 bytes from "stream".
of the CBOR bytestring header from "stream" (Section 3.4.2). If If this is an error, return a "format error".
this is an error, return that error.
4. If "sectionOffsetsLength" is TBD or greater, return an error. 4. Let "urlType" and "urlLength" be the result of reading the type
and argument of a CBOR item from "stream" (Section 3.5.3). If
this is an error or "urlType" is not 3 (a CBOR text string),
return a "format error".
5. Let "sectionOffsetsBytes" be the result of reading 5. Let "fallbackUrlBytes" be the result of reading "urlLength"
"sectionOffsetsLength" bytes from "stream". If bytes from "stream". If this is an error, return a "format
"sectionOffsetsBytes" is an error, return that error. error".
6. Let "sectionOffsets" be the result of parsing one CBOR item 6. Let "fallbackUrl" be the result of parsing ([URL]) the UTF-8
(Section 3.4) from "sectionOffsetsBytes", matching the section- decoding of "fallbackUrlBytes" with no base URL. If either the
offsets rule in the CDDL ([I-D.ietf-cbor-cddl]) above. If UTF-8 decoding or parsing fails, return a "format error".
"sectionOffsets" is an error, return an error.
7. Let "sectionsStart" be the current offset within "stream". For Note: From this point forward, errors also include the fallback
example, if "sectionOffsetsLength" were 52, "sectionsStart" URL to help clients recover.
would be 64.
8. Let "knownSections" be the subset of the Section 6.2 that this 7. If "version" does not have the hex encoding "44 31 00 00 00"
(the CBOR encoding of a 4-byte byte string holding an ASCII "1"
followed by three 0 bytes), return a "version error" with
"fallbackUrl".
Note: RFC EDITOR PLEASE DELETE THIS NOTE; Implementations of
drafts of this specification MUST NOT use the version "1" in
this byte string, and MUST instead define an implementation-
specific string to identify which draft is implemented. This
string SHOULD match the version used in the draft's MIME type
(Section 6.1).
8. Let "sectionLengthsLength" be the result of getting the length
of the CBOR bytestring header from "stream" (Section 3.5.2). If
this is an error, return a "format error" with "fallbackUrl".
9. If "sectionLengthsLength" is 8192 (8*1024) or greater, return a
"format error" with "fallbackUrl".
10. Let "sectionLengthsBytes" be the result of reading
"sectionLengthsLength" bytes from "stream". If
"sectionLengthsBytes" is an error, return a "format error" with
"fallbackUrl".
11. Let "sectionLengths" be the result of parsing one CBOR item
(Section 3.5) from "sectionLengthsBytes", matching the section-
lengths rule in the CDDL ([CDDL]) above. If "sectionLengths" is
an error, return a "format error" with "fallbackUrl".
12. Let ("sectionsType", "numSections") be the result of parsing the
type and argument of a CBOR item from "stream" (Section 3.5.3).
13. If "sectionsType" is not "4" (a CBOR array) or "numSections" is
not half of the length of "sectionLengths", return a "format
error" with "fallbackUrl".
14. Let "sectionsStart" be the current offset within "stream".
For example, if "sectionLengthsLength" were 52 and
"sectionLengths" contained 4 items (2 sections), "sectionsStart"
would be 65 (10 initial bytes + a 2-byte bytestring header to
describe a 52-byte bytestring + 52 bytes of section lengths + a
1-byte array header for the 2 sections).
15. Let "knownSections" be the subset of the Section 6.2 that this
client has implemented. client has implemented.
9. Let "ignoredSections" be an empty set. 16. Let "ignoredSections" be an empty set.
10. For each ""name"" key in "sectionOffsets", if ""name""'s 17. Let "sectionOffsets" be an empty map ([INFRA]) from section
specification in "knownSections" says not to process other names to (offset, length) pairs. These offsets are relative to
sections, add those sections' names to "ignoredSections". the start of "stream".
11. Let "metadata" be an empty map ([INFRA]). 18. Let "currentOffset" be "sectionsStart".
12. For each ""name""/["offset", "length"] triple in 19. For each (""name"", "length") pair of adjacent elements in
"sectionLengths":
1. If ""name""'s specification in "knownSections" says not to
process other sections, add those sections' names to
"ignoredSections".
Note: The "ignoredSections" enables sections that supercede
other sections to be introduced in the future.
Implementations that don't implement any such sections are
free to omit the relevant steps.
2. If "sectionOffsets["name"]" exists, return a "format error"
with "fallbackUrl". That is, duplicate sections are
forbidden.
3. Set "sectionOffsets["name"]" to ("currentOffset", "length").
4. Set "currentOffset" to "currentOffset + length".
20. If the "responses" section is not last in "sectionLengths",
return a "format error" with "fallbackUrl". This allows a
streaming parser to assume that it'll know the requests by the
time their responses arrive.
21. Let "metadata" be a map ([INFRA]) initially containing the
single key/value pair ""primaryUrl""/"fallbackUrl".
22. For each ""name"" --> ("offset", "length") triple in
"sectionOffsets": "sectionOffsets":
1. If ""name"" isn't in "knownSections", continue to the next 1. If ""name"" isn't in "knownSections", continue to the next
triple. triple.
2. If ""name""'s Metadata field is "No", continue to the next 2. If ""name""'s Metadata field (Section 6.2) is "No", continue
triple. to the next triple.
3. If ""name"" is in "ignoredSections", continue to the next 3. If ""name"" is in "ignoredSections", continue to the next
triple. triple.
4. Seek to offset "sectionsStart + offset" in "stream". If 4. Seek to offset "offset" in "stream". If this fails, return
this fails, return an error. a "format error" with "fallbackUrl".
5. Let "sectionContents" be the result of reading "length" 5. Let "sectionContents" be the result of reading "length"
bytes from "stream". If "sectionContents" is an error, bytes from "stream". If "sectionContents" is an error,
return that error. return a "format error" with "fallbackUrl".
6. Follow ""name""'s specification from "knownSections" to 6. Follow ""name""'s specification from "knownSections" to
process the section, passing "sectionContents", "stream", process the section, passing "sectionContents", "stream",
"sectionOffsets", "sectionsStart", and "metadata". If this "sectionOffsets", and "metadata". If this returns an error,
returns an error, return it. return a "format error" with "fallbackUrl".
13. If "metadata" doesn't have entries with keys "requests" and 23. Assert: "metadata" has an entry with the key "primaryUrl".
"manifest", return an error.
14. Return "metadata". 24. If "metadata" doesn't have entries with keys "requests" and
"manifest", return a "format error" with "fallbackUrl".
3.2.1. Parsing the index section 25. Return "metadata".
3.3.1. Parsing the index section
The "index" section defines the set of HTTP requests in the bundle The "index" section defines the set of HTTP requests in the bundle
and identifies their locations in the "responses" section. and identifies their locations in the "responses" section. It
consists of a map from URL strings to arrays consisting of a
"Variants" header field value ([I-D.ietf-httpbis-variants]) followed
by one "location-in-responses" pair for each of the possible
combinations of available-values within the "Variants" value in
lexicographic (row-major) order.
index = {* headers => [ offset: uint, For example, given a "variants-value" of "Accept-Encoding;gzip;br,
length: uint] } Accept-Language;en;fr;ja", the list of "location-in-responses" pairs
will correspond to the "VariantKey"s:
o gzip;en
o gzip;fr
o gzip;ja
o br;en
o br;fr
o br;ja
The order of variant-axes is important. If the "variants-value" were
"Accept-Language;en;fr;ja, Accept-Encoding;gzip;br" instead, the
"location-in-responses" pairs would instead correspond to:
o en;gzip
o en;br
o fr;gzip
o fr;br
o ja;gzip
o ja;br
As a special case, an empty "variants-value" indicates that there is
only one resource at the specified URL and that no content
negotiation is performed.
index = {* whatwg-url => [ variants-value, +location-in-responses ] }
variants-value = bstr
location-in-responses = (offset: uint, length: uint)
A "ResponseMetadata" struct identifies a byte range within the bundle
stream, defined by an integer offset from the start of the stream and
the integer number of bytes in the range.
To parse the index section, given its "sectionContents", the To parse the index section, given its "sectionContents", the
"sectionsStart" offset, the "sectionOffsets" CBOR item, and the "sectionOffsets" map, and the "metadata" map to fill in, the parser
"metadata" map to fill in, the parser MUST do the following: MUST do the following:
1. Let "index" be the result of parsing "sectionContents" as a CBOR 1. Let "index" be the result of parsing "sectionContents" as a CBOR
item matching the "index" rule in the above CDDL (Section 3.4). item matching the "index" rule in the above CDDL (Section 3.5).
If "index" is an error, return an error. If "index" is an error, return an error.
2. Let "requests" be an initially-empty map ([INFRA]) from HTTP 2. Let "requests" be an initially-empty map ([INFRA]) from URLs to
requests ([FETCH]) to structs ([INFRA]) with items named "offset" response descriptions, each of which is either a single
and "length". "location-in-stream" value or a pair of a "Variants" header field
value ([I-D.ietf-httpbis-variants]) and a map from that value's
3. For each "cbor-http-request"/["offset", "length"] triple in possible "Variant-Key"s to "location-in-stream" values, as
"index": described in Section 2.2.
1. Let "headers"/"pseudos" be the result of converting "cbor- 3. Let "MakeRelativeToStream" be a function that takes a "location-
http-request" to a header list and pseudoheaders using the in-responses" value ("offset", "length") and returns a
algorithm in Section 3.5. If this returns an error, return "ResponseMetadata" struct or error by running the following sub-
that error. steps:
2. If "pseudos" does not have keys named ':method' and ':url', 1. If "offset" + "length" is larger than
or its size isn't 2, return an error. "sectionOffsets["responses"].length", return an error.
3. If "pseudos[':method']" is not 'GET', return an error. 2. Otherwise, return a "ResponseMetadata" struct whose offset is
"sectionOffsets["responses"].offset" + "offset" and whose
length is "length".
Note: This could probably support any cacheable 4. For each ("url", "responses") entry in the "index" map:
(Section 4.2.3) of [RFC7231]) and safe (Section 4.2.1 of
[RFC7231]) method, matching PUSH_PROMISE (Section 8.2 of
[RFC7540]), but today that's only HEAD and GET, and HEAD can
be served as a transformation of GET, so this version of the
specification keeps the method simple.
4. Let "parsedUrl" be the result of parsing ([URL]) 1. Let "parsedUrl" be the result of parsing ([URL]) "url" with
"pseudos[':url']" with no base URL. no base URL.
5. If "parsedUrl" is a failure, its fragment is not null, or it 2. If "parsedUrl" is a failure, its fragment is not null, or it
includes credentials, return an error. includes credentials, return an error.
6. Let "http-request" be a new request ([FETCH]) whose: 3. If the first element of "responses" is the empty string:
+ method is "pseudos[':method']", 1. If the length of "responses" is not 3 (i.e. there is more
than one "location-in-responses" in responses), return an
error.
+ url is "parsedUrl", 2. Otherwise, assert that "requests"["parsedUrl"] does not
exist, and set "requests"["parsedUrl"] to
"MakeRelativeToStream(location-in-responses)", where
"location-in-responses" is the second and third elements
of "responses". If that returns an error, return an
error.
+ header list is "headers", and 4. Otherwise:
+ client is null. 1. Let "variants" be the result of parsing the first element
of "responses" as the value of the "Variants" HTTP header
field (Section 2 of [I-D.ietf-httpbis-variants]). If
this fails, return an error.
7. Let "streamOffset" be "sectionsStart + section- 2. Let "variantKeys" be the Cartesian product of the lists
offsets["responses"].offset + offset". That is, offsets in of available-values for each variant-axis in
the index are relative to the start of the "responses" lexicographic (row-major) order. See the examples above.
section.
8. If "offset + length" is greater than 3. If the length of "responses" is not "2 * len(variantKeys)
"sectionOffsets["responses"].length", return an error. + 1", return an error.
9. Set "requests"["http-request"] to a struct whose "offset" 4. Set "requests"["parsedUrl"] to a map from
item is "streamOffset" and whose "length" item is "length". "variantKeys"["i"] to the result of calling
"MakeRelativeToStream" on the "location-in-responses" at
"responses"["2*i+1"] and "responses"["2*i+2"], for "i" in
["0", "len(variantKeys)"). If any "MakeRelativeToStream"
call returns an error, return an error.
4. Set "metadata["requests"]" to "requests". 5. Set "metadata["requests"]" to "requests".
3.2.2. Parsing the manifest section 3.3.2. Parsing the manifest section
The "manifest" section records a single URL identifying the manifest The "manifest" section records a single URL identifying the manifest
of the bundle. The bundle can contain multiple resources at this of the bundle. The URL MUST refer to the one or more response(s)
URL, and the client is expected to content-negotiate for the best contained in the bundle itself.
one. For example, a client might select the one with an "accept"
header of "application/manifest+json" ([appmanifest]) and an "accept- The bundle can contain multiple resources at this URL, and the client
language" header of "es-419". is expected to content-negotiate for the best one. For example, a
client might select the one with an "accept" header of "application/
manifest+json" ([appmanifest]) and an "accept-language" header of
"es-419".
manifest = whatwg-url
manifest = text
To parse the manifest section, given its "sectionContents" and the To parse the manifest section, given its "sectionContents" and the
"metadata" map to fill in, the parser MUST do the following: "metadata" map to fill in, the parser MUST do the following:
1. Let "urlString" be the result of parsing "sectionContents" as a 1. Let "urlString" be the result of parsing "sectionContents" as a
CBOR item matching the above "manifest" rule (Section 3.4. If CBOR item matching the above "manifest" rule (Section 3.5. If
"urlString" is an error, return that error. "urlString" is an error, return that error.
2. Let "url" be the result of parsing ([URL]) "urlString" with no 2. Let "url" be the result of parsing ([URL]) "urlString" with no
base URL. base URL.
3. If "url" is a failure, its fragment is not null, or it includes 3. If "url" is a failure, its fragment is not null, or it includes
credentials, return an error. credentials, return an error.
4. Set "metadata["manifest"]" to "url". 4. Set "metadata["manifest"]" to "url".
3.2.3. Parsing the critical section 3.3.3. Parsing the signatures section
The "signatures" section vouches for the resources in the bundle.
The section can contain as many signatures as needed, each by some
authority, and each covering an arbitrary subset of the resources in
the bundle. Intermediates, including attackers, can remove
signatures from the bundle without breaking the other signatures.
The bundle parser's client is responsible to determine the validity
and meaning of each authority's signatures. In particular, the
algorithm below does not check that signatures are valid. For
example, a client might:
o Use the ecdsa_secp256r1_sha256 algorithm defined in Section 4.2.3
of [TLS1.3] to check the validity of any signature with an EC
public key on the secp256r1 curve.
o Reject all signatures by an RSA public key.
o Treat an X.509 certificate with the CanSignHttpExchanges extension
(Section 4.2 of [I-D.yasskin-http-origin-signed-responses]) and a
valid chain to a trusted root as an authority that vouches for the
authenticity of resources claimed to come from that certificate's
domains.
o Treat an X.509 certificate with another extension or EKU as
vouching that a particular analysis has run over the signed
resources without finding malicious behavior.
A client might also choose different behavior for those kinds of
authorities and keys.
signatures = [
authorities: [*authority],
vouched-subsets: [*{
authority: index-in-authorities,
sig: bstr,
signed: bstr ; Expected to hold a signed-subset item.
}],
]
authority = augmented-certificate
index-in-authorities = uint
signed-subset = {
validity-url: whatwg-url,
auth-sha256: bstr,
date: uint,
expires: uint,
subset-hashes: {+
whatwg-url => [variants-value, +resource-integrity]
},
* tstr => any,
}
resource-integrity = (header-sha256: bstr, payload-integrity-header: tstr)
The "augmented-certificate" CDDL rule comes from Section 3.3 of
[I-D.yasskin-http-origin-signed-responses].
To parse the signatures section, given its "sectionContents", the
"sectionOffsets" map, and the "metadata" map to fill in, the parser
MUST do the following:
1. Let "signatures" be the result of parsing "sectionContents" as a
CBOR item matching the "signatures" rule in the above CDDL
(Section 3.5).
2. Set "metadata["authorities"]" to the list of authorities in the
first element of the "signatures" array.
3. Set "metadata["vouched-subsets"]" to the second element of the
"signatures" array.
3.3.4. Parsing the critical section
The "critical" section lists sections of the bundle that the client The "critical" section lists sections of the bundle that the client
needs to understand in order to load the bundle correctly. Other needs to understand in order to load the bundle correctly. Other
sections are assumed to be optional. sections are assumed to be optional.
critical = [*tstr] critical = [*tstr]
To parse the critical section, given its "sectionContents" and the To parse the critical section, given its "sectionContents" and the
"metadata" map to fill in, the parser MUST do the following: "metadata" map to fill in, the parser MUST do the following:
1. Let "critical" be the result of parsing "sectionContents" as a 1. Let "critical" be the result of parsing "sectionContents" as a
CBOR item matching the above "critical" rule (Section 3.4). If CBOR item matching the above "critical" rule (Section 3.5). If
"critical" is an error, return that error. "critical" is an error, return that error.
2. For each value "sectionName" in the "critical" list, if the 2. For each value "sectionName" in the "critical" list, if the
client has not implemented sections named "sectionName", return client has not implemented sections named "sectionName", return
an error. an error.
This section does not modify the returned metadata. This section does not modify the returned metadata.
3.2.4. The responses section 3.3.5. The responses section
The responses section does not add any items to the bundle metadata The responses section does not add any items to the bundle metadata
map. Instead, its offset and length are used in processing the index map. Instead, its offset and length are used in processing the index
section (Section 3.2.1). section (Section 3.3.1).
3.2.5. Starting from the end 3.3.6. Starting from the end
The length of a bundle is encoded as a big-endian integer inside a The length of a bundle is encoded as a big-endian integer inside a
CBOR byte string at the end of the bundle. CBOR byte string at the end of the bundle.
+------------+-----+----+----+----+----+----+----+----+----+----+ +------------+-----+----+----+----+----+----+----+----+----+----+
| first byte | ... | 48 | 00 | 00 | 00 | 00 | 00 | BC | 61 | 4E | | first byte | ... | 48 | 00 | 00 | 00 | 00 | 00 | BC | 61 | 4E |
+------------+-----+----+----+----+----+----+----+----+----+----+ +------------+-----+----+----+----+----+----+----+----+----+----+
/ \ / \
0xBC614E-10=12345668 omitted bytes 0xBC614E-10=12345668 omitted bytes
Figure 1: Example trailing bytes Figure 1: Example trailing bytes
Parsing from the end allows the bundle to be appended to another Parsing from the end allows the bundle to be appended to another
format such as a self-extracting executable. format such as a self-extracting executable.
To implement Section 2.2.1, taking a sequence of bytes "bytes", the To implement Section 2.2.1, taking a sequence of bytes "bytes", the
client MUST: client MUST:
1. Let "byteStringHeader" be "bytes[bytes.length - 9]". If 1. Let "byteStringHeader" be "bytes[bytes.length - 9]". If
"byteStringHeader is not "0x48` (the CBOR "byteStringHeader is not "0x48` (the CBOR ([CBORbis]) initial
([I-D.ietf-cbor-7049bis]) initial byte for an 8-byte byte byte for an 8-byte byte string), return an error.
string), return an error.
2. Let "bundleLength" be "[bytes[bytes.length - 8], 2. Let "bundleLength" be "[bytes[bytes.length - 8],
bytes[bytes.length])" (the last 8 bytes) interpreted as a big- bytes[bytes.length])" (the last 8 bytes) interpreted as a big-
endian integer. endian integer.
3. If "bundleLength > bytes.length", return an error. 3. If "bundleLength > bytes.length", return an error.
4. Let "stream" be a new stream whose: 4. Let "stream" be a new stream whose:
* Available bytes are "[bytes[bytes.length - bundleLength], * Available bytes are "[bytes[bytes.length - bundleLength],
bytes[bytes.length])". bytes[bytes.length])".
* EOF flag is set. * EOF flag is set.
* Current offset is initially 0. * Current offset is initially 0.
* The seek to offset N and read N bytes operations succeed * The seek to offset N and read N bytes operations succeed
immediately if "currentOffset + N <= bundleLength" and fail immediately if "currentOffset + N <= bundleLength" and fail
otherwise. otherwise.
5. Return the result of running Section 3.2 with "stream" as input. 5. Return the result of running Section 3.3 with "stream" as input.
3.3. Load a response from a bundle 3.4. Load a response from a bundle
The result of Load a bundle's metadata maps each request to a The result of Load a bundle's metadata maps each URL and Variant-Key
response, which consists of headers and a payload. The headers can ([I-D.ietf-httpbis-variants]) to a response, which consists of
be loaded from the bundle's stream before waiting for the payload, headers and a payload. The headers can be loaded from the bundle's
and similarly the payload can be streamed to downstream consumers. stream before waiting for the payload, and similarly the payload can
be streamed to downstream consumers.
response = [headers: bstr .cbor headers, payload: bstr] response = [headers: bstr .cbor headers, payload: bstr]
To implement Section 2.3, the parser MUST run the following steps, To implement Section 2.3, the parser MUST run the following steps,
taking the bundle's "stream" and one "request" and its taking the bundle's "stream", a "request" ([FETCH]), and a
"requestMetadata" as returned by Section 2.2. "responseMetadata" returned by Section 2.2 .
1. Seek to offset "requestMetadata.offset" in "stream". If this 1. Seek to offset "responseMetadata.offset" in "stream". If this
fails, return an error. fails, return an error.
2. Read 1 byte from "stream". If this is an error or isn't "0x82", 2. Read 1 byte from "stream". If this is an error or isn't "0x82",
return an error. return an error.
3. Let "headerLength" be the result of getting the length of a CBOR 3. Let "headerLength" be the result of getting the length of a CBOR
bytestring header from "stream" (Section 3.4.2). If bytestring header from "stream" (Section 3.5.2). If
"headerLength" is an error, return that error. "headerLength" is an error, return that error.
4. If "headerLength" is TBD or greater, return an error. 4. If "headerLength" is 524288 (512*1024) or greater, return an
error.
5. Let "headerCbor" be the result of reading "headerLength" bytes 5. Let "headerCbor" be the result of reading "headerLength" bytes
from "stream" and parsing a CBOR item from them matching the from "stream" and parsing a CBOR item from them matching the
"headers" CDDL rule. If either the read or parse returns an "headers" CDDL rule. If either the read or parse returns an
error, return that error. error, return that error.
6. Let "headers"/"pseudos" be the result of converting "cbor-http- 6. Let ("headers", "pseudos") be the result of converting
request" to a header list and pseudoheaders using the algorithm "headerCbor" to a header list and pseudoheaders using the
in Section 3.5. If this returns an error, return that error. algorithm in Section 3.6. If this returns an error, return that
error.
7. If "pseudos" does not have a key named ':status' or its size 7. If "pseudos" does not have a key named ':status' or its size
isn't 1, return an error. isn't 1, return an error.
8. If "pseudos[':status']" isn't exactly 3 ASCII decimal digits, 8. If "pseudos[':status']" isn't exactly 3 ASCII decimal digits,
return an error. return an error.
9. Let "payloadLength" be the result of getting the length of a 9. If "headers" does not contain a "Content-Type" header, return an
CBOR bytestring header from "stream" (Section 3.4.2). If error.
The client MUST interpret the following payload as this
specified media type instead of trying to sniff a media type
from the bytes of the payload, for example by appending an
artificial "X-Content-Type-Options: nosniff" header field
([FETCH]) to "headers".
10. Let "payloadLength" be the result of getting the length of a
CBOR bytestring header from "stream" (Section 3.5.2). If
"payloadLength" is an error, return that error. "payloadLength" is an error, return that error.
10. If "stream.currentOffset + payloadLength != 11. If "stream.currentOffset + payloadLength !=
requestMetadata.offset + requestMetadata.length", return an responseMetadata.offset + responseMetadata.length", return an
error. error.
11. Let "body" be a new body ([FETCH]) whose stream is a tee'd copy 12. Let "body" be a new body ([FETCH]) whose stream is a tee'd copy
of "stream" starting at the current offset and ending after of "stream" starting at the current offset and ending after
"payloadLength" bytes. "payloadLength" bytes.
TODO: Add the rest of the details of creating a "ReadableStream" TODO: Add the rest of the details of creating a "ReadableStream"
object. object.
12. Let "response" be a new response ([FETCH]) whose: 13. Let "response" be a new response ([FETCH]) whose:
* Url list is "request"'s url list, * Url list is "request"'s url list,
* status is "pseudos[':status']", * status is "pseudos[':status']",
* header list is "headers", and * header list is "headers", and
* body is "body". * body is "body".
13. Return "response". 14. Return "response".
3.4. Parsing CBOR items 3.5. Parsing CBOR items
Parsing a bundle involves parsing many CBOR items. All of these Parsing a bundle involves parsing many CBOR items. All of these
items need to be canonically encoded. items need to be deterministically encoded.
3.4.1. Parse a known-length item 3.5.1. Parse a known-length item
To parse a CBOR item ([I-D.ietf-cbor-7049bis]), optionally matching a To parse a CBOR item ([CBORbis]), optionally matching a CDDL rule
CDDL rule ([I-D.ietf-cbor-cddl]), from a sequence of bytes, "bytes", ([CDDL]), from a sequence of bytes, "bytes", the parser MUST do the
the parser MUST do the following: following:
1. If "bytes" are not a well-formed CBOR item, return an error. 1. If "bytes" are not a well-formed CBOR item, return an error.
2. If "bytes" does not satisfy the core canonicalization 2. If "bytes" does not satisfy the core deterministic encoding
requirements from Section 4.9 of [I-D.ietf-cbor-7049bis], return requirements from Section 4.2.1 of [CBORbis], return an error.
an error. This format does not use floating point values or This format does not use floating point values or tags, so this
tags, so this specification does not add any canonicalization specification does not add any deterministic encoding rules for
rules for them. them.
3. If "bytes" includes extra bytes after the encoding of a CBOR 3. If "bytes" includes extra bytes after the encoding of a CBOR
item, return an error. item, return an error.
4. Let "item" be the result of decoding "bytes" as a CBOR item. 4. Let "item" be the result of decoding "bytes" as a CBOR item.
5. If a CDDL rule was specified, but "item" does not match it, 5. If a CDDL rule was specified, but "item" does not match it,
return an error. return an error.
6. Return "item". 6. Return "item".
3.4.2. Parsing variable-length data from a bytestring 3.5.2. Parsing variable-length data from a bytestring
Bundles encode variable-length data in CBOR bytestrings, which are Bundles encode variable-length data in CBOR bytestrings, which are
prefixed with their length. This algorithm returns the number of prefixed with their length. This algorithm returns the number of
bytes in the variable-length item and sets the stream's current bytes in the variable-length item and sets the stream's current
offset to the first byte of the contents. offset to the first byte of the contents.
To get the length of a CBOR bytestring header from a bundle's stream, To get the length of a CBOR bytestring header from a bundle's stream,
the parser MUST do the following: the parser MUST do the following:
1. Let ("type", "argument") be the result of parsing the type and
argument of a CBOR item from the stream (Section 3.5.3). If this
returns an error, return that error.
2. If "type" is not "2", the item is not a bytestring. Return an
error.
3. Return "argument".
3.5.3. Parsing the type and argument of a CBOR item
To parse the type and argument of a CBOR item from a bundle's stream,
the parser MUST do the following. This algorithm returns a pair of
the CBOR major type 0-7 inclusive, and a 64-bit integral argument for
the CBOR item:
1. Let "firstByte" be the result of reading 1 byte from the stream. 1. Let "firstByte" be the result of reading 1 byte from the stream.
If "firstByte" is an error, return that error. If "firstByte" is an error, return that error.
2. If "firstByte & 0xE0" is not "0x40", the item is not a 2. Let "type" be "(firstByte & 0xE0) / 0x20".
bytestring. Return an error.
3. If "firstByte & 0x1F" is: 3. If "firstByte & 0x1F" is:
0..23, inclusive Return "firstByte". 0..23, inclusive Return ("type", "firstByte & 0x1F").
24 Let "content" be the result of reading 1 byte from the stream. 24 Let "content" be the result of reading 1 byte from the stream.
If "content" is an error or is less than 24, return an error. If "content" is an error or is less than 24, return an error.
25 Let "content" be the result of reading 2 bytes from the 25 Let "content" be the result of reading 2 bytes from the
stream. If "content" is an error or its first byte is 0, stream. If "content" is an error or its first byte is 0,
return an error. return an error.
26 Let "content" be the result of reading 4 bytes from the 26 Let "content" be the result of reading 4 bytes from the
stream. If "content" is an error or its first two bytes are stream. If "content" is an error or its first two bytes are
0, return an error. 0, return an error.
27 Let "content" be the result of reading 8 bytes from the 27 Let "content" be the result of reading 8 bytes from the
stream. If "content" is an error or its first four bytes are stream. If "content" is an error or its first four bytes are
0, return an error. 0, return an error.
28..31, inclusive Return an error. 28..31, inclusive Return an error. Note: This intentionally
does not support indefinite-length items.
4. Return the big-endian integer encoded in "content". 4. Let "argument" be the big-endian integer encoded in "content".
3.5. Interpreting CBOR HTTP headers 5. Return ("type", "argument").
3.6. Interpreting CBOR HTTP headers
Bundles represent HTTP requests and responses as a list of headers, Bundles represent HTTP requests and responses as a list of headers,
matching the following CDDL ([I-D.ietf-cbor-cddl]): matching the following CDDL ([CDDL]):
headers = {* bstr => bstr} headers = {* bstr => bstr}
Pseudo-headers starting with a ":" provide the non-header information Pseudo-headers starting with a ":" provide the non-header information
needed to create a request or response as appropriate needed to create a request or response as appropriate
To convert a CBOR item "item" into a [FETCH] header list and To convert a CBOR item "item" into a [FETCH] header list and
pseudoheaders, parsers MUST do the following: pseudoheaders, parsers MUST do the following:
1. If "item" doesn't match the "headers" rule in the above CDDL, 1. If "item" doesn't match the "headers" rule in the above CDDL,
return an error. return an error.
2. Let "headers" be a new header list ([FETCH]). 2. Let "headers" be a new header list ([FETCH]).
3. Let "pseudos" be an empty map ([INFRA]). 3. Let "pseudos" be an empty map ([INFRA]).
skipping to change at page 15, line 5 skipping to change at page 21, line 14
To convert a CBOR item "item" into a [FETCH] header list and To convert a CBOR item "item" into a [FETCH] header list and
pseudoheaders, parsers MUST do the following: pseudoheaders, parsers MUST do the following:
1. If "item" doesn't match the "headers" rule in the above CDDL, 1. If "item" doesn't match the "headers" rule in the above CDDL,
return an error. return an error.
2. Let "headers" be a new header list ([FETCH]). 2. Let "headers" be a new header list ([FETCH]).
3. Let "pseudos" be an empty map ([INFRA]). 3. Let "pseudos" be an empty map ([INFRA]).
4. For each pair "name"/"value" in "item": 4. For each pair ("name", "value") in "item":
1. If "name" contains any upper-case or non-ASCII characters, 1. If "name" contains any upper-case or non-ASCII characters,
return an error. This matches the requirement in return an error. This matches the requirement in
Section 8.1.2 of [RFC7540]. Section 8.1.2 of [RFC7540].
2. If "name" starts with a ':': 2. If "name" starts with a ':':
1. Assert: "pseudos[name]" does not exist, because CBOR maps 1. Assert: "pseudos[name]" does not exist, because CBOR maps
cannot contain duplicate keys. cannot contain duplicate keys.
skipping to change at page 15, line 31 skipping to change at page 21, line 40
header in [FETCH], return an error. header in [FETCH], return an error.
4. Assert: "headers" does not contain ([FETCH]) "name", because 4. Assert: "headers" does not contain ([FETCH]) "name", because
CBOR maps cannot contain duplicate keys and an earlier step CBOR maps cannot contain duplicate keys and an earlier step
rejected upper-case bytes. rejected upper-case bytes.
Note: This means that a response cannot set more than one Note: This means that a response cannot set more than one
cookie, because the "Set-Cookie" header ([RFC6265]) has to cookie, because the "Set-Cookie" header ([RFC6265]) has to
appear multiple times to set multiple cookies. appear multiple times to set multiple cookies.
5. Append "name"/"value" to "headers". 5. Append ("name", "value") to "headers".
5. Return "headers"/"pseudos". 5. Return ("headers", "pseudos").
4. Guidelines for bundle authors 4. Guidelines for bundle authors
Bundles SHOULD consist of a single CBOR item satisfying the core Bundles SHOULD consist of a single CBOR item satisfying the core
canonicalization requirements (Section 3.4) and matching the deterministic encoding requirements (Section 3.5) and matching the
"webbundle" CDDL rule in Section 3.1. "webbundle" CDDL rule in Section 3.1.
5. Security Considerations 5. Security Considerations
5.1. Version skew
Bundles currently have no mechanism for ensuring that the signed Bundles currently have no mechanism for ensuring that the signed
exchanges they contain constitute a consistent version of those exchanges they contain constitute a consistent version of those
resources. Even if a website never has a security vulnerability when resources. Even if a website never has a security vulnerability when
resources are fetched at a single time, an attacker might be able to resources are fetched at a single time, an attacker might be able to
combine a set of resources pulled from different versions of the combine a set of resources pulled from different versions of the
website to build a vulnerable site. While the vulnerable site could website to build a vulnerable site. While the vulnerable site could
have occurred by chance on a client's machine due to normal HTTP have occurred by chance on a client's machine due to normal HTTP
caching, bundling allows an attacker to guarantee that it happens. caching, bundling allows an attacker to guarantee that it happens.
Future work in this specification might allow a bundle to constrain Future work in this specification might allow a bundle to constrain
its resources to come from a consistent version. its resources to come from a consistent version.
5.2. Content sniffing
While modern browsers tend to trust the "Content-Type" header sent
with a resource, especially when accompanied by "X-Content-Type-
Options: nosniff", plugins will sometimes search for executable
content buried inside a resource and execute it in the context of the
origin that served the resource, leading to XSS vulnerabilities. For
example, some PDF reader plugins look for "%PDF" anywhere in the
first 1kB and execute the code that follows it.
The "application/webbundle" format defined above includes URLs and
request headers early in the format, which an attacker could use to
cause these plugins to sniff a bad content type.
To avoid vulnerabilities, in addition to the response header
requirements in Section 3.2, servers are advised to only serve an
"application/webbundle" resource from a domain if it would also be
safe for that domain to serve the bundle's content directly, and to
follow at least one of the following strategies:
1. Only serve bundles from dedicated domains that don't have access
to sensitive cookies or user storage.
2. Generate bundles "offline", that is, in response to a trusted
author submitting content or existing signatures reaching a
certain age, rather than in response to untrusted-reader queries.
3. Do all of:
1. If the bundle's contained URLs (e.g. in the manifest and
index) are derived from the request for the bundle, percent-
encode [3] ([URL]) any bytes that are greater than 0x7E or
are not URL code points [4] ([URL]) in these URLs. It is
particularly important to make sure no unescaped nulls (0x00)
or angle brackets (0x3C and 0x3E) appear.
2. Similarly, if the request headers for any contained resource
are based on the headers sent while requesting the bundle,
only include request header field names *and values* that
appear in a static allowlist. Keep the set of allowed
request header fields smaller than 24 elements to prevent
attackers from controlling a whole CBOR length byte.
3. Restrict the number of items a request can direct the server
to include in a bundle to less than 12, again to prevent
attackers from controlling a whole CBOR length byte.
4. Do not reflect request header fields into the set of response
headers.
If the server serves responses that are written by a potential
attacker but then escaped, the "application/webbundle" format allows
the attacker to use the length of the response to control a few bytes
before the start of the response. Any existing mechanisms that
prevent polyglot documents probably keep working in the face of this
new attack, but we don't have a guarantee of that.
To encourage servers to include the "X-Content-Type-Options: nosniff"
header field, clients SHOULD reject bundles served without it.
6. IANA considerations 6. IANA considerations
6.1. Internet Media Type Registration 6.1. Internet Media Type Registration
IANA maintains the registry of Internet Media Types [RFC6838] at IANA maintains the registry of Internet Media Types [RFC6838] at
https://www.iana.org/assignments/media-types [3]. https://www.iana.org/assignments/media-types [5].
o Type name: application o Type name: application
o Subtype name: webbundle o Subtype name: webbundle
o Required parameters: N/A o Required parameters:
* v: A string denoting the version of the file format.
([RFC5234] ABNF: "version = 1*(DIGIT/%x61-7A)") The version
defined in this specification is "1".
Note: RFC EDITOR PLEASE DELETE THIS NOTE; Implementations of
drafts of this specification MUST NOT use simple integers to
describe their versions, and MUST instead define
implementation-specific strings to identify which draft is
implemented.
o Optional parameters: N/A o Optional parameters: N/A
o Encoding considerations: binary o Encoding considerations: binary
o Security considerations: See Section 5 of this document. o Security considerations: See Section 5 of this document.
o Interoperability considerations: N/A o Interoperability considerations: N/A
o Published specification: This document o Published specification: This document
skipping to change at page 16, line 52 skipping to change at page 24, line 41
o Person & email address to contact for further information: See the o Person & email address to contact for further information: See the
Author's Address section of this specification. Author's Address section of this specification.
o Intended usage: COMMON o Intended usage: COMMON
o Restrictions on usage: N/A o Restrictions on usage: N/A
o Author: See the Author's Address section of this specification. o Author: See the Author's Address section of this specification.
o Change controller: The IESG iesg@ietf.org [4] o Change controller: The IESG iesg@ietf.org [6]
o Provisional registration? (standards tree only): Not yet. o Provisional registration? (standards tree only): Not yet.
6.2. Web Bundle Section Name Registry 6.2. Web Bundle Section Name Registry
IANA is directed to create a new registry with the following IANA is directed to create a new registry with the following
attributes: attributes:
Name: Web Bundle Section Names Name: Web Bundle Section Names
Review Process: Specification Required Review Process: Specification Required
Initial Assignments: Initial Assignments:
+--------------+---------------+----------+ +--------------+---------------+----------+-------------------------+
| Section Name | Specification | Metadata | | Section Name | Specification | Metadata | Metadata Fields |
+--------------+---------------+----------+ +--------------+---------------+----------+-------------------------+
| "index" | Section 3.2.1 | Yes | | "index" | Section 3.3.1 | Yes | "requests" |
| | | | | | | | |
| "manifest | Section 3.2.2 | Yes | | "manifest" | Section 3.3.2 | Yes | "manifest" |
| | | | | | | | |
| "critical | Section 3.2.3 | Yes | | "signatures" | Section 3.3.3 | Yes | "authorities", |
| | | | | | | | "vouched-subsets" |
| "responses" | Section 3.2.4 | No | | | | | |
+--------------+---------------+----------+ | "critical" | Section 3.3.4 | Yes | |
| | | | |
| "responses" | Section 3.3.5 | No | |
+--------------+---------------+----------+-------------------------+
Requirements on new assignments: Requirements on new assignments:
Section Names MUST be encoded in UTF-8. Section Names MUST be encoded in UTF-8.
Assignments must specify whether the section is parsed during Assignments must specify whether the section is parsed during
Load a bundle's metadata (Metadata=Yes) or not (Metadata=No). Load a bundle's metadata (Metadata=Yes) or not (Metadata=No).
The section's specification can use the bytes making up the section, The section's specification can use the bytes making up the section,
the bundle's stream (Section 2.1), the "sectionOffsets" CBOR item the bundle's stream (Section 2.1), and the "sectionOffsets" map
(Section 3.2), and the offset within the stream where sections start, (Section 3.3), as input, and MUST say if an error is returned, and
as input, and MUST say if an error is returned, and otherwise what otherwise what items, if any, are added to the map that Section 3.3
items, if any, are added to the map that Section 3.2 returns. A returns. A section's specification MAY say that, if it is present,
section's specification MAY say that, if it is present, another another section is not processed.
section is not processed.
7. References 7. References
7.1. Normative References 7.1. Normative References
[appmanifest] [appmanifest]
Caceres, M., Christiansen, K., Lamouri, M., Kostiainen, Caceres, M., Christiansen, K., Lamouri, M., Kostiainen,
A., Dolin, R., and M. Giuca, "Web App Manifest", World A., Dolin, R., and M. Giuca, "Web App Manifest", World
Wide Web Consortium WD WD-appmanifest-20180523, May 2018, Wide Web Consortium WD WD-appmanifest-20180523, May 2018,
<https://www.w3.org/TR/2018/WD-appmanifest-20180523>. <https://www.w3.org/TR/2018/WD-appmanifest-20180523>.
[FETCH] WHATWG, "Fetch", June 2018, [CBORbis] Bormann, C. and P. Hoffman, "Concise Binary Object
Representation (CBOR)", draft-ietf-cbor-7049bis-06 (work
in progress), July 2019.
[CDDL] Birkholz, H., Vigano, C., and C. Bormann, "Concise Data
Definition Language (CDDL): A Notational Convention to
Express Concise Binary Object Representation (CBOR) and
JSON Data Structures", RFC 8610, DOI 10.17487/RFC8610,
June 2019, <https://www.rfc-editor.org/info/rfc8610>.
[FETCH] WHATWG, "Fetch", July 2019,
<https://fetch.spec.whatwg.org/>. <https://fetch.spec.whatwg.org/>.
[I-D.ietf-cbor-7049bis] [I-D.ietf-httpbis-variants]
Bormann, C. and P. Hoffman, "Concise Binary Object Nottingham, M., "HTTP Representation Variants", draft-
Representation (CBOR)", draft-ietf-cbor-7049bis-02 (work ietf-httpbis-variants-05 (work in progress), March 2019.
in progress), March 2018.
[I-D.ietf-cbor-cddl] [I-D.yasskin-http-origin-signed-responses]
Birkholz, H., Vigano, C., and C. Bormann, "Concise data Yasskin, J., "Signed HTTP Exchanges", draft-yasskin-http-
definition language (CDDL): a notational convention to origin-signed-responses-06 (work in progress), July 2019.
express CBOR data structures", draft-ietf-cbor-cddl-02
(work in progress), February 2018.
[INFRA] WHATWG, "Infra", June 2018, [INFRA] WHATWG, "Infra", July 2019,
<https://infra.spec.whatwg.org/>. <https://infra.spec.whatwg.org/>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997, DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>. <https://www.rfc-editor.org/info/rfc2119>.
[RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax
Protocol (HTTP/1.1): Semantics and Content", RFC 7231, Specifications: ABNF", STD 68, RFC 5234,
DOI 10.17487/RFC7231, June 2014, DOI 10.17487/RFC5234, January 2008,
<https://www.rfc-editor.org/info/rfc7231>. <https://www.rfc-editor.org/info/rfc5234>.
[RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext [RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext
Transfer Protocol Version 2 (HTTP/2)", RFC 7540, Transfer Protocol Version 2 (HTTP/2)", RFC 7540,
DOI 10.17487/RFC7540, May 2015, DOI 10.17487/RFC7540, May 2015,
<https://www.rfc-editor.org/info/rfc7540>. <https://www.rfc-editor.org/info/rfc7540>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>. May 2017, <https://www.rfc-editor.org/info/rfc8174>.
[SRI] Akhawe, D., Braun, F., Marier, F., and J. Weinberger, [SRI] Akhawe, D., Braun, F., Marier, F., and J. Weinberger,
"Subresource Integrity", World Wide Web Consortium "Subresource Integrity", World Wide Web Consortium
Recommendation REC-SRI-20160623, June 2016, Recommendation REC-SRI-20160623, June 2016,
<http://www.w3.org/TR/2016/REC-SRI-20160623>. <http://www.w3.org/TR/2016/REC-SRI-20160623>.
[URL] WHATWG, "URL", June 2018, <https://url.spec.whatwg.org/>. [URL] WHATWG, "URL", July 2019, <https://url.spec.whatwg.org/>.
7.2. Informative References 7.2. Informative References
[I-D.yasskin-http-origin-signed-responses]
Yasskin, J., "Signed HTTP Exchanges", draft-yasskin-http-
origin-signed-responses-03 (work in progress), March 2018.
[I-D.yasskin-webpackage-use-cases] [I-D.yasskin-webpackage-use-cases]
Yasskin, J., "Use Cases and Requirements for Web Yasskin, J., "Use Cases and Requirements for Web
Packages", draft-yasskin-webpackage-use-cases-01 (work in Packages", draft-yasskin-webpackage-use-cases-01 (work in
progress), March 2018. progress), March 2018.
[RFC6265] Barth, A., "HTTP State Management Mechanism", RFC 6265, [RFC6265] Barth, A., "HTTP State Management Mechanism", RFC 6265,
DOI 10.17487/RFC6265, April 2011, DOI 10.17487/RFC6265, April 2011,
<https://www.rfc-editor.org/info/rfc6265>. <https://www.rfc-editor.org/info/rfc6265>.
[RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type [RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type
Specifications and Registration Procedures", BCP 13, Specifications and Registration Procedures", BCP 13,
RFC 6838, DOI 10.17487/RFC6838, January 2013, RFC 6838, DOI 10.17487/RFC6838, January 2013,
<https://www.rfc-editor.org/info/rfc6838>. <https://www.rfc-editor.org/info/rfc6838>.
[TLS1.3] Rescorla, E., "The Transport Layer Security (TLS) Protocol
Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
<https://www.rfc-editor.org/info/rfc8446>.
7.3. URIs 7.3. URIs
[1] https://mailarchive.ietf.org/arch/search/?email_list=art [1] https://www.ietf.org/mailman/listinfo/wpack
[2] https://github.com/WICG/webpackage [2] https://github.com/WICG/webpackage
[3] https://www.iana.org/assignments/media-types [3] https://url.spec.whatwg.org/#percent-encode
[4] mailto:iesg@ietf.org [4] https://url.spec.whatwg.org/#url-code-points
Appendix A. Acknowledgements [5] https://www.iana.org/assignments/media-types
[6] mailto:iesg@ietf.org
Appendix A. Change Log
RFC EDITOR PLEASE DELETE THIS SECTION.
draft-01
o Include only section lengths in the section index, requiring
sections to be listed in order.
o Have the "index" section map URLs to sets of responses negotiated
using the Variants system ([I-D.ietf-httpbis-variants]).
o Require the "manifest" to be embedded into the bundle.
o Add a content sniffing security consideration.
o Add a version string to the format and its mime type.
o Add a fallback URL in a fixed location in the format, and use that
fallback URL as the primary URL of the bundle.
o Add a "signatures" section to let authorities (like domain-trusted
X.509 certificates) vouch for subsets of a bundle.
o Use the CBORbis "deterministic encoding" requirements instead of
"canonicalization" requirements.
Appendix B. Acknowledgements
Thanks to the Chrome loading team, especially Kinuko Yasuda and
Kouhei Ueno for making the format work well when streamed.
Author's Address Author's Address
Jeffrey Yasskin Jeffrey Yasskin
Google Google
Email: jyasskin@chromium.org Email: jyasskin@chromium.org
 End of changes. 126 change blocks. 
258 lines changed or deleted 641 lines changed or added

This html diff was produced by rfcdiff 1.47. The latest version is available from http://tools.ietf.org/tools/rfcdiff/