@@ -52,7 +52,9 @@ urlPrefix:https://w3c.github.io/hr-time/#;spec:hr-time
5252urlPrefix:https://tc39.es/ecma262/#;type:dfn;spec:ecma-262
5353 url:realm;text:realm
5454 url:sec-list-and-record-specification-type;text:Record
55- url:current-realm;text:current realm
55+ url:sec-parsetext;text:ParseText
56+ url:prod-Script;text:Script
57+ url:script-record;text:Script Record
5658</pre>
5759
5860<pre class=biblio>
@@ -2161,6 +2163,17 @@ Unless stated otherwise, it is false.
21612163
21622164<p class=note> This flag is for exclusive use by HTML's render-blocking mechanism. [[!HTML]]
21632165
2166+ <p class=XXX> A <a for=/>request</a> has an associated
2167+ <dfn export for=request>no-cors media request state</dfn> ...
2168+
2169+ <p class=note> This is for exclusive use by the <a>opaque-response-safelist check</a> .
2170+
2171+ <p> A <a for=/>request</a> has an associated
2172+ <dfn for=request>no-cors JavaScript fallback encoding</dfn> (an <a for=/>encoding</a> ). Unless
2173+ stated otherwise, it is <a for=/>UTF-8</a> .
2174+
2175+ <p class=note> This is for exclusive use by the <a>opaque-response-safelist check</a> .
2176+
21642177<hr>
21652178
21662179<p> A <a for=/>request</a> has an associated
@@ -3275,6 +3288,285 @@ through TLS using ALPN. The protocol cannot be spoofed through HTTP requests in
32753288</div>
32763289
32773290
3291+ <h3 id=orb>Opaque-response blocking</h3>
3292+
3293+ <div class=note>
3294+ <p> Opaque-response blocking, also known as <abbr> ORB</abbr> , is a network filter that blocks access
3295+ to <a>opaque filtered responses</a> . These responses would likely would not have been useful to the
3296+ fetching party. Blocking them reduces information leakage to potential attackers.
3297+
3298+ <p> Essentially, CSS, JavaScript, images, and media (audio and video) can be requested across
3299+ origins without the <a>CORS protocol</a> . And unfortunately except for CSS there is no MIME type
3300+ enforcement. This algorithm aims to block as many responses as possible that are not one of these
3301+ types (or are newer variants of those types) to avoid leaking their contents through side channels.
3302+
3303+ <p> The network filter combines pro-active blocking based on response headers, sniffing a limited
3304+ set of bytes, and ultimately falls back to a full parse due to unfortunate (lack of) design
3305+ decisions in the early days of the web platform. As a result there are still quite a few responses
3306+ whose secrets can end up being revealed to attackers. Web developers are strongly encouraged to use
3307+ the `<code http-header> Cross-Origin-Resource-Policy</code> ` response header to defend them.
3308+ </div>
3309+
3310+
3311+ <h4 id=orb-algorithm>The opaque-response-safelist check</h4>
3312+
3313+ <p> The <dfn>opaque-response-safelist check</dfn> , given a <a for=/>request</a> <var> request</var>
3314+ and a <a for=/>response</a> <var> response</var> , is to run these steps:
3315+
3316+ <ol>
3317+ <li><p> Let <var> mimeType</var> be the result of <a>extracting a MIME type</a> from
3318+ <var> response</var> 's <a for=response>header list</a> .
3319+
3320+ <li><p> Let <var> nosniff</var> be the result of <a>determining nosniff</a> given
3321+ <var> response</var> 's <a for=response>header list</a> .
3322+
3323+ <li>
3324+ <p> If <var> mimeType</var> is not failure, then:
3325+
3326+ <ol>
3327+ <li><p> If <var> mimeType</var> is an <a>opaque-response-safelisted MIME type</a> , then return
3328+ true.
3329+
3330+ <li><p> If <var> mimeType</var> is an <a>opaque-response-blocklisted-never-sniffed MIME type</a> ,
3331+ then return false.
3332+
3333+ <li><p> If <var> response</var> 's <a for=response>status</a> is 206 and <var> mimeType</var> is an
3334+ <a>opaque-response-blocklisted MIME type</a> , then return false.
3335+
3336+ <li><p> If <var> nosniff</var> is true and <var> mimeType</var> is an
3337+ <a>opaque-response-blocklisted MIME type</a> or its <a for="MIME type">essence</a> is
3338+ "<code> text/plain</code> ", then return false.
3339+ </ol>
3340+
3341+ <li><p> If <var> request</var> 's <a for=request>no-cors media request state</a> is
3342+ "<code> subsequent</code> ", then return true.
3343+
3344+ <li><p> If <var> response</var> 's <a for=response>status</a> is 206 and
3345+ <a>validate a partial response</a> given 0 and <var> response</var> returns invalid, then return
3346+ false.
3347+ <!-- TODO Integrate https://wicg.github.io/background-fetch/#validate-a-partial-response into Fetch -->
3348+
3349+ <li><p> Let <var> bytes</var> be the result of running
3350+ <a>obtain a copy of the first 1024 bytes of response</a> given <var> response</var> .
3351+
3352+ <li><p> If <var> bytes</var> is failure, then return false.
3353+
3354+ <li>
3355+ <p> If the <a>audio or video type pattern matching algorithm</a> given <var> bytes</var> does not
3356+ return undefined, then:
3357+
3358+ <ol>
3359+ <li><p> If <var> requests</var> 's <a for=request>no-cors media request state</a> is not
3360+ "<code> initial</code> ", then return false.
3361+
3362+ <li><p> If <var> response</var> 's <a for=response>status</a> is not 200 or 206, then return false.
3363+
3364+ <li><p> Return true.
3365+ </ol>
3366+
3367+ <li><p> If <var> requests</var> 's <a for=request>no-cors media request state</a> is not
3368+ "<code> N/A</code> ", then return false.
3369+
3370+ <li><p> If the <a>image type pattern matching algorithm</a> given <var> bytes</var> does not return
3371+ undefined, then return true.
3372+
3373+ <li>
3374+ <p> If <var> nosniff</var> is true, then return false.
3375+
3376+ <p class=note> This check is made late as unfortunately images and media are always sniffed.
3377+
3378+ <li><p> If <var> response</var> 's <a for=response>status</a> is not an <a>ok status</a> , then return
3379+ false.
3380+
3381+ <li>
3382+ <p> If <var> mimeType</var> is failure, then return true.
3383+
3384+ <p class=note> This could be improved at somewhat significant cost. See
3385+ <a href=https://github.com/annevk/orb/issues/28>annevk/orb #28</a> .
3386+
3387+ <li><p> If <var> mimeType</var> 's <a for="MIME type">essence</a> <a for=string>starts with</a>
3388+ "<code> audio/</code> ", "<code> image/</code> ", or "<code> video/</code> ", then return false.
3389+
3390+ <li><p> Return <a>determine if response is JavaScript and not JSON</a> given <var> response</var> .
3391+ </ol>
3392+
3393+ <hr>
3394+
3395+ <p> To <dfn>obtain a copy of the first 1024 bytes of response</dfn> , given a <a for=/>response</a>
3396+ <var> response</var> , run these steps:
3397+
3398+ <ol>
3399+ <li><p> Let <var> first1024Bytes</var> be null.
3400+
3401+ <li>
3402+ <p> <a for=/>In parallel</a> :
3403+
3404+ <ol>
3405+ <li><p> Let <var> bytes</var> be the empty <a for=/>byte sequence</a> .
3406+
3407+ <li><p> Let <var> transformStream</var> be a new {{TransformStream}} .
3408+
3409+ <li>
3410+ <p> Let <var> transformAlgorithm</var> given a <var> chunk</var> be these steps:
3411+
3412+ <ol>
3413+ <li><p> <a for=ReadableStream>Enqueue</a> <var> chunk</var> in <var> transformStream</var> .
3414+
3415+ <li>
3416+ <p> If <var> first1024Bytes</var> is null, then:
3417+
3418+ <ol>
3419+ <li><p> Let <var> chunkBytes</var> be
3420+ <a lt="get a copy of the bytes held by the buffer source">a copy of the bytes held by</a>
3421+ <var> chunk</var> .
3422+
3423+ <li><p> Append <var> chunkBytes</var> to <var> bytes</var> .
3424+
3425+ <li>
3426+ <p> If <var> bytes</var> 's <a for="byte sequencue">length</a> is greater than 1024, then:
3427+
3428+ <ol>
3429+ <li><p> Truncate <var> bytes</var> from the end so that it only contains 1024 bytes.
3430+
3431+ <li><p> Set <var> first1024Bytes</var> to <var> bytes</var> .
3432+ </ol>
3433+ </ol>
3434+ </ol>
3435+
3436+ <li><p> Let <var> flushAlgorithm</var> be this step: if <var> first1024Bytes</var> is null, then set
3437+ <var> first1024Bytes</var> to <var> bytes</var> .
3438+
3439+ <li><p> <a for=TransformStream>Set up</a> <var> transformStream</var> with
3440+ <a for="TransformStream/set up"><i>transformAlgorithm</i></a> set to
3441+ <var> transformAlgorithm</var> and <a for="TransformStream/set up"><i>flushAlgorithm</i></a> set
3442+ to <var> flushAlgorithm</var> .
3443+
3444+ <li><p> Set <var> response</var> 's <a for=response>body</a>' s <a for=body>stream</a> to the result
3445+ of <var> response</var> 's <a for=response>body</a>' s <a for=body>stream</a>
3446+ <a for=TransformStream>piped through</a> <var> transformStream</var> .
3447+ </ol>
3448+
3449+ <li><p> Wait until <var> first1024Bytes</var> is non-null or <var> response</var> 's
3450+ <a for=response>body</a> 's <a for=body>stream</a> is <a for=ReadableStream>errored</a> .
3451+
3452+ <li><p> If <var> first1024Bytes</var> is null, then return failure.
3453+
3454+ <li> Return <var> first1024Bytes</var> .
3455+ </ol>
3456+
3457+ <hr>
3458+
3459+ <p> To <dfn>determine if response is JavaScript and not JSON</dfn> given a <a for=/>response</a>
3460+ <var> response</var> , run these steps:</p>
3461+
3462+ <ol>
3463+ <li><p> Let <var> responseBodyBytes</var> be null.
3464+
3465+ <li>
3466+ <p> Let <var> processBody</var> given a <a for=/>byte sequence</a> <var> bytes</var> be these steps:
3467+
3468+ <ol>
3469+ <li><p> Set <var> responseBodyBytes</var> to <var> bytes</var> .
3470+
3471+ <li><p> Set <var> response</var> 's <a for=response>body</a> to the <a for="body with type">body</a>
3472+ of the result of <a for=BodyInit>safely extracting</a> <var> bytes</var> .
3473+ </ol>
3474+
3475+ <li><p> Let <var> processBodyError</var> be this step: set <var> responseBodyBytes</var> to failure.
3476+
3477+ <li><p> <a>Fully read</a> <var> response</var> 's <a for=response>body</a> given <a>processBody</a>
3478+ and <var> processBodyError</var> .
3479+
3480+ <li><p> Wait for <var> responseBodyBytes</var> to be non-null.
3481+
3482+ <li><p> If <var> responseBodyBytes</var> is failure, then return false.
3483+
3484+ <li><p> <a for=/>Assert</a> : <var> responseBodyBytes</var> is a <a for=/>byte sequence</a> .
3485+
3486+ <li>
3487+ <p> If <a>parse JSON bytes to a JavaScript value</a> given <var> responseBodyBytes</var> does not
3488+ throw, then return false. If it throws, catch the exception and ignore it.
3489+
3490+ <p class=note> If there is an exception, <var> response</var> is not JSON. If there is not, it is.
3491+
3492+ <li><p> Let <var> potentialMIMETypeForEncoding</var> be the result of <a>extracting a MIME type</a>
3493+ given <var> response</var> 's <a for=response>header list</a> .
3494+
3495+ <li>
3496+ <p> Let <var> encoding</var> be the result of <a>legacy extracting an encoding</a> given
3497+ <var> potentialMIMETypeForEncoding</var> and <var> request</var> 's
3498+ <a for=request>no-cors JavaScript fallback encoding</a> .
3499+
3500+ <p class=note> Equivalently to <a>fetch a classic script</a> , this ignores the
3501+ <a for="MIME type" lt=essence>MIME type essence</a> .
3502+
3503+ <li><p> Let <var> sourceText</var> be the result of <a for=/>decoding</a>
3504+ <var> responseBodyBytes</var> given <var> encoding</var> .
3505+
3506+ <li><p> If <a>ParseText</a> (<var> sourceText</var> , <a>Script</a> ) returns a <a>Script Record</a> ,
3507+ then return true.
3508+ <!-- Ideally HTML owns this so ECMAScript changes don't end up impacting Fetch. We could
3509+ potentially make this use "create a classic script" instead with some mock data. Maybe that is
3510+ better? -->
3511+
3512+ <li><p> Return false.
3513+ </ol>
3514+
3515+
3516+ <h4 id=orb-mime-type-sets>New MIME type sets</h4>
3517+
3518+ <p class=note> The definitions in this section are solely for the purpose of abstracting parts of the
3519+ <a>opaque-response-safelist check</a> . They are not suited for usage elsewhere.
3520+
3521+ <p> An <dfn>opaque-response-safelisted MIME type</dfn> is a <a>JavaScript MIME type</a> or a
3522+ <a for=/>MIME type</a> whose <a for="MIME type">essence</a> is "<code> text/css</code> " or
3523+ "<code> image/svg+xml</code> ".
3524+
3525+ <p> An <dfn>opaque-response-blocklisted MIME type</dfn> is an <a>HTML MIME type</a> ,
3526+ <a>JSON MIME type</a> , or <a>XML MIME type</a> .
3527+
3528+ <p> An <dfn>opaque-response-blocklisted-never-sniffed MIME type</dfn> is a <a for=/>MIME type</a>
3529+ whose <a for="MIME type">essence</a> is one of:
3530+
3531+ <ul class=brief>
3532+ <li> "<code> application/gzip</code> "
3533+ <li> "<code> application/msexcel</code> "
3534+ <li> "<code> application/mspowerpoint</code> "
3535+ <li> "<code> application/msword</code> "
3536+ <li> "<code> application/msword-template</code> "
3537+ <li> "<code> application/pdf</code> "
3538+ <li> "<code> application/vnd.ces-quickpoint</code> "
3539+ <li> "<code> application/vnd.ces-quicksheet</code> "
3540+ <li> "<code> application/vnd.ces-quickword</code> "
3541+ <li> "<code> application/vnd.ms-excel</code> "
3542+ <li> "<code> application/vnd.ms-excel.sheet.macroenabled.12</code> "
3543+ <li> "<code> application/vnd.ms-powerpoint</code> "
3544+ <li> "<code> application/vnd.ms-powerpoint.presentation.macroenabled.12</code> "
3545+ <li> "<code> application/vnd.ms-word</code> "
3546+ <li> "<code> application/vnd.ms-word.document.12</code> "
3547+ <li> "<code> application/vnd.ms-word.document.macroenabled.12</code> "
3548+ <li> "<code> application/vnd.msword</code> "
3549+ <li> "<code> application/vnd.openxmlformats-officedocument.presentationml.presentation</code> "
3550+ <li> "<code> application/vnd.openxmlformats-officedocument.presentationml.template</code> "
3551+ <li> "<code> application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</code> "
3552+ <li> "<code> application/vnd.openxmlformats-officedocument.spreadsheetml.template</code> "
3553+ <li> "<code> application/vnd.openxmlformats-officedocument.wordprocessingml.document</code> "
3554+ <li> "<code> application/vnd.openxmlformats-officedocument.wordprocessingml.template</code> "
3555+ <li> "<code> application/vnd.presentation-openxml</code> "
3556+ <li> "<code> application/vnd.presentation-openxmlm</code> "
3557+ <li> "<code> application/vnd.spreadsheet-openxml</code> "
3558+ <li> "<code> application/vnd.wordprocessing-openxml</code> "
3559+ <li> "<code> application/x-gzip</code> "
3560+ <li> "<code> application/x-protobuf</code> "
3561+ <li> "<code> application/x-protobuffer</code> "
3562+ <li> "<code> application/zip</code> "
3563+ <li> "<code> multipart/byteranges</code> "
3564+ <li> "<code> multipart/signed</code> "
3565+ <li> "<code> text/event-stream</code> "
3566+ <li> "<code> text/csv</code> "
3567+ </ul>
3568+
3569+
32783570
32793571<h2 id=http-extensions>HTTP extensions</h2>
32803572
@@ -5237,19 +5529,23 @@ these steps:
52375529 <li><p> Set <var> response</var> and <var> internalResponse</var> to the result of running
52385530 <a>HTTP-network-or-cache fetch</a> given <var> fetchParams</var> .
52395531
5240- <li>
5241- <p> If < var>request </var> 's <a for=request> response tainting </a> is " <code> cors </code> " and a
5242- <a>CORS check</a> for <var> request</var> and <var> response</var> returns failure, then return a
5243- <a>network error</a> .
5532+ <li><p> If <var> request </var> 's <a for=request>response tainting</a> is " <code> opaque </code> ",
5533+ < var>response </var> 's <a for=response>status </a> is not a <a>redirect status</a> , and the
5534+ <a>opaque-response-safelist check</a> given <var> request</var> and <var> response</var> returns
5535+ false, then return a <a>network error</a> .
52445536
5245- <p class=note> As the <a>CORS check </a> is not to be applied to <a for=/>responses</a> whose
5246- <a for=response>status </a> is 304 or 407, or <a for=/>responses</a> from a service worker for
5247- that matter, it is applied here .
5537+ <li><p> If <var> request </var> 's <a for=request>response tainting </a> is " <code> cors </code> " and
5538+ the <a>CORS check </a> for <var> request </var> and <var> response </var> returns failure, then return
5539+ a <a>network error</a> .
52485540
52495541 <li><p> If the <a>TAO check</a> for <var> request</var> and <var> response</var> returns failure,
52505542 then set <var> request</var> 's <a for=request>timing allow failed flag</a> .
52515543 </ol>
52525544
5545+ <p class=note> As the <a>opaque-response-safelist check</a> , <a>CORS check</a> , and
5546+ <a>TAO check</a> are not to be applied to <a for=/>responses</a> whose <a for=response>status</a>
5547+ is 304 or 407, or to <a for=/>responses</a> from a service worker, they are applied here.
5548+
52535549 <li>
52545550 <p> If either <var> request</var> 's <a for=request>response tainting</a> or <var>response</var>' s
52555551 <a for=response>type</a> is "<code> opaque</code> ", and the
@@ -9152,6 +9448,7 @@ Mohamed Zergaoui,
91529448Mohammed Zubair Ahmed<!-- M-ZubairAhmed; GitHub -->,
91539449Moritz Kneilmann,
91549450Ms2ger,
9451+ Nathan Froyd,
91559452Nico Schlömer,
91569453Nicolás Peña Moreno,
91579454Nidhi Jaju,
0 commit comments