Skip to content

Commit 5c5e6ca

Browse files
committed
Define opaque-response blocking
This is good enough for early review, but there are a number of issues that still need resolving: https://github.com/annevk/orb/labels/mvp. There are also some inline TODO comments. A PR against HTML is needed to ensure it passes the appropriate metadata for media element and classic script requests. We might also want to depend on HTML for parsing JavaScript.
1 parent c4532ce commit 5c5e6ca

File tree

1 file changed

+215
-1
lines changed

1 file changed

+215
-1
lines changed

fetch.bs

+215-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ urlPrefix:https://w3c.github.io/hr-time/#;spec:hr-time
3333
url:dfn-coarsened-shared-current-time;text:coarsened shared current time
3434
url:dfn-unsafe-shared-current-time;text:unsafe shared current time
3535
type:typedef;url:dom-domhighrestimestamp;text:DOMHighResTimeStamp
36+
37+
urlPrefix: https://tc39.es/ecma262/;type:dfn;spec:ecma-262
38+
url:sec-parsetext;text:ParseText
39+
url:prod-Script;text:Script
40+
url:script-record;text:Script Record
3641
</pre>
3742

3843
<pre class=link-defaults>
@@ -1839,6 +1844,16 @@ Unless stated otherwise, it is false.
18391844

18401845
<p class=note>This is for exclusive use by HTML's navigate algorithm. [[!HTML]]
18411846

1847+
<p class=XXX>A <a for=/>request</a> has an associated
1848+
<dfn export for=request>no-cors media request state</dfn> ...
1849+
1850+
<p class=note>This is for exclusive use by the <a>opaque-response-safelist check</a>.
1851+
1852+
<p>A <a for=/>request</a> has an associated <a>no-cors JavaScript fallback encoding</a> (an
1853+
<a for=/>encoding</a>). Unless stated otherwise, it is <a for=/>UTF-8</a>.
1854+
1855+
<p class=note>This is for exclusive use by the <a>opaque-response-safelist check</a>.
1856+
18421857
<hr>
18431858

18441859
<p>A <a for=/>request</a> has an associated
@@ -2871,6 +2886,198 @@ run these steps:
28712886
</ol>
28722887

28732888

2889+
<h3 id=orb>Opaque-response blocking</h3>
2890+
2891+
<div class=note>
2892+
<p>Opaque-response blocking, also known as <abbr>ORB</abbr>, is a network filter that blocks access
2893+
to <a>opaque filtered responses</a>. These responses would likely would not have been useful to the
2894+
fetching party. Blocking them reduces information leakage to potential attackers.
2895+
2896+
<p>Essentially, CSS, JavaScript, images, and media (audio and video) can be requested across
2897+
origins without the <a>CORS protocol</a>. And unfortunately except for CSS there is no MIME type
2898+
enforcement. This algorithm aims to block as many responses as possible that are not one of these
2899+
types (or are newer variants of those types) to avoid leaking their contents through side channels.
2900+
2901+
<p>The network filter combines pro-active blocking based on response headers, sniffing a limited
2902+
set of bytes, and ultimately falls back to a full parse due to unfortunate (lack of) design
2903+
decisions in the early days of the web platform. As a result there are still quite a few responses
2904+
whose secrets can end up being revealed to attackers. Web developers are strongly encouraged to use
2905+
the `<code http-header>Cross-Origin-Resource-Policy</code>` response header to defend them.
2906+
</div>
2907+
2908+
2909+
<h4 id=orb-algorithm>The opaque-response-safelist check</h4>
2910+
2911+
<p>The <dfn>opaque-response-safelist check</dfn>, given a <a for=/>request</a> <var>request</var>
2912+
and a <a for=/>response</a> <var>response</var>, is to run these steps:
2913+
2914+
<ol>
2915+
<li><p>Let <var>mimeType</var> be the result of <a>extracting a MIME type</a> from
2916+
<var>response</var>'s <a for=response>header list</a>.
2917+
2918+
<li><p>Let <var>nosniff</var> be the result of <a>determining nosniff</a> given
2919+
<var>response</var>'s <a for=response>header list</a>.
2920+
2921+
<li>
2922+
<p>If <var>mimeType</var> is not failure, then:
2923+
2924+
<ol>
2925+
<li><p>If <var>mimeType</var> is an <a>opaque-response-safelisted MIME type</a>, then return
2926+
true.
2927+
2928+
<li><p>If <var>mimeType</var> is an <a>opaque-response-blocklisted-never-sniffed MIME type</a>,
2929+
then return false.
2930+
2931+
<li><p>If <var>response</var>'s <a for=response>status</a> is 206 and <var>mimeType</var> is an
2932+
<a>opaque-response-blocklisted MIME type</a>, then return false.
2933+
2934+
<li><p>If <var>nosniff</var> is true and <var>mimeType</var> is an
2935+
<a>opaque-response-blocklisted MIME type</a> or its <a for="MIME type">essence</a> is
2936+
"<code>text/plain</code>", then return false.
2937+
</ol>
2938+
2939+
<li><p>If <var>request</var>'s <a for=request>no-cors media request state</a> is
2940+
"<code>subsequent</code>", then return true.
2941+
2942+
<li><p>If <var>response</var>'s <a for=response>status</a> is 206 and
2943+
<a>validate a partial response</a> given 0 and <var>response</var> returns invalid, then return
2944+
false.
2945+
<!-- TODO Integrate https://wicg.github.io/background-fetch/#validate-a-partial-response into Fetch -->
2946+
2947+
<li><p>Wait for 1024 bytes of <var>response</var>'s <a for=response>body</a> or end-of-file,
2948+
whichever comes first and let <var>bytes</var> be those bytes.
2949+
<!-- TODO Obtaining these bytes needs to be defined in terms of a transform stream. -->
2950+
2951+
<li>
2952+
<p>If the <a>audio or video type pattern matching algorithm</a> given <var>bytes</var> does not
2953+
return undefined, then:
2954+
2955+
<ol>
2956+
<li><p>If <var>requests</var>'s <a for=request>no-cors media request state</a> is not
2957+
"<code>initial</code>", then return false.
2958+
2959+
<li><p>If <var>response</var>'s <a for=response>status</a> is not 200 or 206, then return false.
2960+
2961+
<li><p>Return true.
2962+
</ol>
2963+
2964+
<li><p>If <var>requests</var>'s <a for=request>no-cors media request state</a> is not
2965+
"<code>N/A</code>", then return false.
2966+
2967+
<li><p>If the <a>image type pattern matching algorithm</a> given <var>bytes</var> does not return
2968+
undefined, then return true.
2969+
2970+
<li>
2971+
<p>If <var>nosniff</var> is true, then return false.
2972+
2973+
<p class=note>This check is made late as unfortunately images and media are always sniffed.
2974+
2975+
<li><p>If <var>response</var>'s <a for=response>status</a> is not an <a>ok status</a>, then return
2976+
false.
2977+
2978+
<li>
2979+
<p>If <var>mimeType</var> is failure, then return true.
2980+
2981+
<p class=note>This could be improved at somewhat significant cost. See
2982+
<a href=https://github.com/annevk/orb/issues/28>annevk/orb #28</a>.
2983+
2984+
<li><p>If <var>mimeType</var>'s <a for="MIME type">essence</a> <a for=string>starts with</a>
2985+
"<code>audio/</code>", "<code>image/</code>", or "<code>video/</code>", then return false.
2986+
2987+
<li><p>Let <var>responseBodyBytes</var> be null.
2988+
2989+
<li>
2990+
<p>Let <var>processBody</var> given a <a for=/>byte sequence</a> <var>bytes</var> be these steps:
2991+
2992+
<ol>
2993+
<li><p>Set <var>responseBodyBytes</var> to <var>bytes</var>.
2994+
2995+
<li><p>Set <var>response</var>'s <a for=response>body</a> to the <a for="body with type">body</a>
2996+
of the result of <a for=BodyInit>safely extracting</a> <var>bytes</var>.
2997+
</ol>
2998+
2999+
<li><p>Let <var>processBodyError</var> be this step: set <var>responseBodyBytes</var> to failure.
3000+
3001+
<li><p><a>Fully read</a> <var>response</var>'s <a for=response>body</a> given <a>processBody</a>
3002+
and <var>processBodyError</var>.
3003+
3004+
<li><p>Wait for <var>responseBodyBytes</var> to be non-null.
3005+
3006+
<li><p>If <var>responseBodyBytes</var> is failure, then return false.
3007+
3008+
<li><p><a for=/>Assert</a>: <var>responseBodyBytes</var> is a <a for=/>byte sequence</a>.
3009+
3010+
<li><p>If <a>parse JSON bytes to a JavaScript value</a> given <var>responseBodyBytes</var> does not
3011+
throw, then return false. If it throws, catch the exception and ignore it.
3012+
3013+
<li><p>Let <var>sourceText</var> be the result of <a for=/>decoding</a>
3014+
<var>responseBodyBytes</var> given <var>request</var>'s
3015+
<a for=request>no-cors JavaScript fallback encoding</a>.
3016+
3017+
<li><p>If <a>ParseText</a>(<var>sourceText</var>, <a>Script</a>) returns a <a>Script Record</a>,
3018+
then return true.
3019+
<!-- Ideally HTML owns this so ECMAScript changes don't end up impacting Fetch. We could
3020+
potentially make this use "create a classic script" instead with some mock data. Maybe that is
3021+
better? -->
3022+
3023+
<li><p>Return false.
3024+
</ol>
3025+
3026+
3027+
<h4 id=orb-mime-type-sets>New MIME type sets</h4>
3028+
3029+
<p class=note>The definitions in this section are solely for the purpose of abstracting parts of the
3030+
<a>opaque-response-safelist check</a>. They are not suited for usage elsewhere.
3031+
3032+
<p>An <dfn>opaque-response-safelisted MIME type</dfn> is a <a>JavaScript MIME type</a> or a
3033+
<a for=/>MIME type</a> whose <a for="MIME type">essence</a> is "<code>text/css</code>" or
3034+
"<code>image/svg+xml</code>".
3035+
3036+
<p>An <dfn>opaque-response-blocklisted MIME type</dfn> is an <a>HTML MIME type</a>,
3037+
<a>JSON MIME type</a>, or <a>XML MIME type</a>.
3038+
3039+
<p>An <dfn>opaque-response-blocklisted-never-sniffed MIME type</dfn> is a <a for=/>MIME type</a>
3040+
whose <a for="MIME type">essence</a> is one of:
3041+
3042+
<ul class=brief>
3043+
<li>"<code>application/gzip</code>"
3044+
<li>"<code>application/msexcel</code>"
3045+
<li>"<code>application/mspowerpoint</code>"
3046+
<li>"<code>application/msword</code>"
3047+
<li>"<code>application/msword-template</code>"
3048+
<li>"<code>application/pdf</code>"
3049+
<li>"<code>application/vnd.ces-quickpoint</code>"
3050+
<li>"<code>application/vnd.ces-quicksheet</code>"
3051+
<li>"<code>application/vnd.ces-quickword</code>"
3052+
<li>"<code>application/vnd.ms-excel</code>"
3053+
<li>"<code>application/vnd.ms-excel.sheet.macroenabled.12</code>"
3054+
<li>"<code>application/vnd.ms-powerpoint</code>"
3055+
<li>"<code>application/vnd.ms-powerpoint.presentation.macroenabled.12</code>"
3056+
<li>"<code>application/vnd.ms-word</code>"
3057+
<li>"<code>application/vnd.ms-word.document.12</code>"
3058+
<li>"<code>application/vnd.ms-word.document.macroenabled.12</code>"
3059+
<li>"<code>application/vnd.msword</code>"
3060+
<li>"<code>application/vnd.openxmlformats-officedocument.presentationml.presentation</code>"
3061+
<li>"<code>application/vnd.openxmlformats-officedocument.presentationml.template</code>"
3062+
<li>"<code>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</code>"
3063+
<li>"<code>application/vnd.openxmlformats-officedocument.spreadsheetml.template</code>"
3064+
<li>"<code>application/vnd.openxmlformats-officedocument.wordprocessingml.document</code>"
3065+
<li>"<code>application/vnd.openxmlformats-officedocument.wordprocessingml.template</code>"
3066+
<li>"<code>application/vnd.presentation-openxml</code>"
3067+
<li>"<code>application/vnd.presentation-openxmlm</code>"
3068+
<li>"<code>application/vnd.spreadsheet-openxml</code>"
3069+
<li>"<code>application/vnd.wordprocessing-openxml</code>"
3070+
<li>"<code>application/x-gzip</code>"
3071+
<li>"<code>application/x-protobuf</code>"
3072+
<li>"<code>application/x-protobuffer</code>"
3073+
<li>"<code>application/zip</code>"
3074+
<li>"<code>multipart/byteranges</code>"
3075+
<li>"<code>multipart/signed</code>"
3076+
<li>"<code>text/event-stream</code>"
3077+
<li>"<code>text/csv</code>"
3078+
</ul>
3079+
3080+
28743081

28753082
<h2 id=http-extensions>HTTP extensions</h2>
28763083

@@ -4075,8 +4282,14 @@ steps:
40754282

40764283
<li><p>Set <var>request</var>'s <a for=request>response tainting</a> to "<code>opaque</code>".
40774284

4078-
<li><p>Return the result of running <a>scheme fetch</a> given <var>fetchParams</var>.
4285+
<li><p>Let <var>opaqueResponse</var> be the result of running <a>scheme fetch</a> given
4286+
<var>fetchParams</var>.
40794287
<!-- file URLs end up here as they are not same-origin typically. -->
4288+
4289+
<li><p>If the <a>opaque-response-safelist check</a> given <var>request</var> and
4290+
<var>opaqueResponse</var> returns true, then return <var>opaqueResponse</var>.
4291+
4292+
<li><p>Return a <a>network error</a>.
40804293
</ol>
40814294

40824295
<dt><var>request</var>'s <a for=request>current URL</a>'s <a for=url>scheme</a> is not an
@@ -8305,6 +8518,7 @@ Mohamed Zergaoui,
83058518
Mohammed Zubair Ahmed<!-- M-ZubairAhmed; GitHub -->,
83068519
Moritz Kneilmann,
83078520
Ms2ger,
8521+
Nathan Froyd,
83088522
Nico Schlömer,
83098523
Nicolás Peña Moreno,
83108524
Nikhil Marathe,

0 commit comments

Comments
 (0)