Re: Preloading using JS instead of a tag

Let me send a short summary here:

- We, Google, had a discussion internally.
- We'll start an origin trial with <link rel=webbundle>, tentatively, as
long as we don't find any further security concern. We'll update the
explainer as well.
- Our primary motivation for the origin trial is to measure the benefits of
this feature, webbundle subresource loading, in terms of the performance.
We collect performance data and feedback so that we can know whether this
feature is really worth or not for the platform earlier.
- <link rel=webbundle> is not a final decision. We continue to discuss
which one is the best for the platform; <script type=webbundle>, <link
rel=webbundle>, or any other ideas.
- If you have any opinions, we'd really appreciate that!

On Tue, Sep 22, 2020 at 4:11 AM Jeffrey Yasskin <jyasskin@google.com> wrote:

> On Mon, Sep 21, 2020 at 7:53 AM Krzysztof Kotowicz <koto@google.com>
> wrote:
>
>>
>>
>> On Fri, Sep 18, 2020 at 8:04 PM Jeffrey Yasskin <jyasskin@google.com>
>> wrote:
>>
>>> On Fri, Sep 18, 2020 at 1:29 AM Krzysztof Kotowicz <koto@google.com>
>>> wrote:
>>>
>>>>
>>>>
>>>> On Fri, Sep 18, 2020 at 9:08 AM Hayato Ito <hayato@google.com> wrote:
>>>>
>>>>> Let me update the status.
>>>>>
>>>>> We are considering using <script> elements as a declarative form [1],
>>>>> instead of <link> elements, to address security concerns.
>>>>> However, before proceeding this way, we'd like to confirm one thing;
>>>>> Can't we use <link> elements even if we limit subresources loaded from the
>>>>> bundle only to the same-origin resources to the bundle's URL?
>>>>>
>>>>> Let me explain with an example:
>>>>>
>>>>> Suppose we have a bundle, "https://example.com/sub.wbn", which
>>>>> includes the following three resources:
>>>>> - https://example.com/a.png
>>>>> - https://example.com/b.png
>>>>> - https://other.com/c.png
>>>>>
>>>>> We use this bundle as follows:
>>>>>
>>>>> <link rel=webbundle href="https://example.com/sub.wbn"
>>>>>       resources="https://example.com/a.png https://example.com/b.png
>>>>> https://other.com/c.png">
>>>>> <img src=https://example.com/a.png>
>>>>> <img src=https://example.com/b.png>
>>>>> <img src=https://other.com/c.png>
>>>>>
>>>>> In this case,
>>>>> - We load a.png and b.png from the bundle because their origins,
>>>>> https://example.com, are the same to the bundle's origin,
>>>>> https://example.com.
>>>>> - however, we don't load c.png from the bundle because its origin,
>>>>> https://other.com, is different from the bundle's origin,
>>>>> https://example.com.
>>>>>
>>>>> This means that a bundle is effectively used to package subresources
>>>>> in the one same origin. The different origin subresources are unlikely to
>>>>> be packaged in one bundle.
>>>>>
>>>>> Suppose that we limit subresource loading this way, does security
>>>>> concerns still apply to the usage of <link> elements?
>>>>>
>>>>>
>>>> Thanks for the update! I think there are still some security concerns
>>>> remaining. The concerns are much smaller of course (and limiting to the
>>>> origin is a smart idea!), but I worry that the risk is not really about the
>>>> origins here, but rather about being able to change the content under a
>>>> given URL (without, say, a service worker installation) on the embedding
>>>> page. It "feels" like it should require a capability of injecting a script
>>>> element to the embedder.
>>>>
>>>> To make sure I understand the setup correctly - in order to have a
>>>> correct (i.e. able to replace the resources) bundle served from
>>>> example.com, one needs to have the capability to serve anything under
>>>> example.com (e.g. the TLS keys)? If the attacker needs to have
>>>> anything less than that, then the potential attack is still possible for
>>>> shared origins (e.g. https://foo.example/~alice/bundle.wbn could
>>>> replace https://foo.example/~bob resources requested on another page).
>>>> The shared origin is usually not an issue, as Alice can trivially XSS Bob,
>>>> but here the attack (replacing the resources by injecting a <link>) is
>>>> happening on _another_ page, e.g. a https://i.only.trust.bob.example/.
>>>>
>>>
>>> As mentioned in
>>> https://github.com/WICG/webpackage/issues/580#issuecomment-679473747,
>>> we avoid this particular attack by adopting a path restriction similar to
>>> the one Service Workers use. So, say there's a bundle at
>>> https://foo.example/~alice/bundle.wbn. It contains the following
>>> resources:
>>>
>>> 1) https://foo.example/~alice/bundle.wbn/script1.js (doesn't work on a
>>> filesystem, but a web server could serve it)
>>> 2) https://foo.example/~alice/script2.js
>>> 3) https://foo.example/~bob/script3.js
>>>
>>> The current proposal says it's authoritative for (1) and (2) by default,
>>> but needs a response header (similar to Service-Worker-Allowed) to be
>>> authoritative for (3). We could make it authoritative for just (1) or for
>>> nothing at all by default, and still allow the header to expand the
>>> authoritative scope.
>>>
>>>
>> Thanks for clarifying that! Glad to know that the attack was taked into
>> consideration! I would still have somewhat better sleep if controlling
>> which scripts run on a page (or blocking ones from running) required
>> injecting a <script> node.
>>
>
> Note that a `<link rel=preload href="the_script.js"
> integrity="sha256-WrongValue">` also blocks the script from running. I
> believe the new risk is around changing what scripts run if the bundled and
> non-bundled scripts are different for some reason, maybe because one is
> stale or a server allows the attacker to write new content into a directory
> that contains (directly or indirectly) scripts.
>
> Jeffrey
>
>
>> It just feels too powerful, and similar in capabilities to WICG import
>> maps <https://github.com/WICG/import-maps>. I worry, perhaps too much,
>> that we might be enabling future bugs through this, as that behavior is
>> quite surprising. But that's not a hard NO at this point.
>>
>>
>>> Jeffrey
>>>
>>>
>>>> [1] POC CL:
>>>>> https://chromium-review.googlesource.com/c/chromium/src/+/2402927
>>>>>
>>>>> On Mon, Aug 31, 2020 at 4:15 PM Hayato Ito <hayato@google.com> wrote:
>>>>>
>>>>>> Regarding <script> as a declarative form, It seems there is a
>>>>>> similar proposal, <script type="importamap">.
>>>>>>
>>>>>> (copy/pasted from https://github.com/WICG/import-maps)
>>>>>>
>>>>>> <script type="importmap">
>>>>>> {
>>>>>>   "imports": {
>>>>>>     "moment": "/node_modules/moment/src/moment.js",
>>>>>>     "lodash": "/node_modules/lodash-es/lodash.js"
>>>>>>   }
>>>>>> }
>>>>>> </script>
>>>>>>
>>>>>> We'll report back once we know the status of <script
>>>>>> type="importmap">. We might learn from there.
>>>>>>
>>>>>> On Fri, Aug 28, 2020 at 10:55 PM Yoav Weiss <yoavweiss@google.com>
>>>>>> wrote:
>>>>>>
>>>>>>> Krzysztof and I talked about this offline and reached some
>>>>>>> conclusions:
>>>>>>>
>>>>>>>    - `<script>` seems like the right declarative home for this - to
>>>>>>>    make sure it's defended against similarly to other XSS vectors
>>>>>>>    - A declarative solution can still be racy if specified naively,
>>>>>>>    and the processing model should make sure that it is not (e.g. by not
>>>>>>>    loading the bundle if resources covered by it were already fetched)
>>>>>>>
>>>>>>>
>>>>>>> On Fri, Aug 28, 2020 at 12:42 PM Krzysztof Kotowicz <koto@google.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> I understand that. My question is, are we actually avoiding races
>>>>>>>> if we kept, say, link element?
>>>>>>>>
>>>>>>>> <script>
>>>>>>>> document.head.appendChild(scriptWithBundleUrl);
>>>>>>>> document.head.appendChild(webBundleLink);
>>>>>>>> </script>
>>>>>>>>
>>>>>>>> On Fri, Aug 28, 2020 at 12:11 PM Yoav Weiss <yoavweiss@google.com>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> Think of the following HTML, based on Hayato's example:
>>>>>>>>> ```
>>>>>>>>> <link rel=stylesheet href="https://www.example.com/unbundled.css">
>>>>>>>>> <script>
>>>>>>>>> document.webbundles.add({
>>>>>>>>>   href: 'https://www.example.com/foo.wbn
>>>>>>>>> <https://www.exmaple.com/foo.wbn>',
>>>>>>>>>   resources: ['https://www.example.com/a.js
>>>>>>>>> <https://www.exmaple.com/a.png>', 'https://www.example.com/b.css
>>>>>>>>> <https://www.exmaple.com/b.css>', ...]
>>>>>>>>> });
>>>>>>>>> </script>
>>>>>>>>> <link rel=stylesheet href="https://www.example.com/b.css">
>>>>>>>>> <script src="https://www.example.com/a.js">
>>>>>>>>> ```
>>>>>>>>>
>>>>>>>>> The browser (all browsers, in subtly different ways) would take
>>>>>>>>> the HTML tokens, scan them and speculatively preload a.js and b.css based
>>>>>>>>> on that, before executing the inline script (which is blocked on the style
>>>>>>>>> above it).
>>>>>>>>> Aside: I believe that even without the blocking "unbundled" style
>>>>>>>>> the race would be often lost. May merit testing in the different browsers.
>>>>>>>>>
>>>>>>>>> While we could ask developers to not do that, and always trigger
>>>>>>>>> request for bundled resources from JS, that would have significant
>>>>>>>>> ergonomics, adoption and performance implications, and I'd much rather we
>>>>>>>>> don't go that route.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Fri, Aug 28, 2020 at 12:01 PM Krzysztof Kotowicz <
>>>>>>>>> koto@google.com> wrote:
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Fri, Aug 28, 2020 at 11:49 AM Yoav Weiss <yoavweiss@google.com>
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>> If we want WebBundles to fit into today's pages (which e.g.
>>>>>>>>>>> include `<script src>` tags), we need an imperative mechanism to load them
>>>>>>>>>>> and tell the browser about the resources they contain.
>>>>>>>>>>> An imperative mechanism to load them would only be effective for
>>>>>>>>>>> dynamically loaded resources, which are inherently slower to discover. It
>>>>>>>>>>> would be a shame if we ended up encouraging that pattern.
>>>>>>>>>>>
>>>>>>>>>>> Would moving away from `<link>` to e.g. `<base>` (as Mike
>>>>>>>>>>> suggested) or `<script type=bundle>` address your concerns?
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> I would prefer base or script, yes. But is the raciness problem
>>>>>>>>>> solved, given that DOM is mutable from JS? That would need to be addressed
>>>>>>>>>> anyhow if I understand correctly.
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On Fri, Aug 28, 2020 at 11:33 AM Krzysztof Kotowicz <
>>>>>>>>>>> koto@google.com> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> The DOM tree can also change dynamically. If the element that
>>>>>>>>>>>> controls the bundle loading is inserted via JS, would that
>>>>>>>>>>>> also affect raciness? If so, there's little way around it, short of
>>>>>>>>>>>> ignoring the behavior when added dynamically (which might be surprising for
>>>>>>>>>>>> authors).
>>>>>>>>>>>>
>>>>>>>>>>>> On Fri, Aug 28, 2020 at 10:58 AM Yoav Weiss <
>>>>>>>>>>>> yoavweiss@google.com> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> An imperative mechanism to load bundles would be inherently
>>>>>>>>>>>>> racy - the preloadScanner would not be aware of it, and can kick off script
>>>>>>>>>>>>> requests before their bundles are discovered.
>>>>>>>>>>>>>
>>>>>>>>>>>>> If `<link>` is a risky choice here, I'm fine with a different
>>>>>>>>>>>>> tag to do the same. I have no strong opinion regarding what would be a good
>>>>>>>>>>>>> alternative.
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Fri, Aug 28, 2020 at 10:44 AM Mike West <mkwst@google.com>
>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>> I don't have a strong opinion about the mechanism, but I do
>>>>>>>>>>>>>> think the risk ascribed to the `<link>` approach is real.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> If declarative mechanisms are preferred, I wonder if an
>>>>>>>>>>>>>> extension to `<base>` would be more appropriate here than an extension to
>>>>>>>>>>>>>> `<link>`. `<base>` already affects resource loading across the page (in
>>>>>>>>>>>>>> kinda terrible ways, but still!), and so already needs to be addressed by
>>>>>>>>>>>>>> folks who aim to sanitize user input.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> It also is suggested to be invalid outside of `<head>`, which
>>>>>>>>>>>>>> would be similarly helpful if browsers implemented that as a requirement;
>>>>>>>>>>>>>> there doesn't seem to be a WPT for it, and Chromium at least would fail.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> -mike
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On Fri, Aug 28, 2020 at 9:18 AM Hayato Ito <hayato@google.com>
>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Hi Ryosuke. Thanks for sharing concerns.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I'm wondering if we have imperative JS APIs which
>>>>>>>>>>>>>>> are *equivalent* to declarative one, some of the security concerns will be
>>>>>>>>>>>>>>> addressed?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Imperative JS APIs can be something like:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> <script>
>>>>>>>>>>>>>>> // Tentative ideas. API surfaces do not matter for now.
>>>>>>>>>>>>>>> document.webbundles.add({
>>>>>>>>>>>>>>>   href: 'https://www.exmaple.com/foo.wbn',
>>>>>>>>>>>>>>>   resources: ['https://www.exmaple.com/a.png', '
>>>>>>>>>>>>>>> https://www.exmaple.com/b.css', ...]
>>>>>>>>>>>>>>> });
>>>>>>>>>>>>>>> </script>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> # Then, UA will try to load 'https://www.exmaple.com/a.png'
>>>>>>>>>>>>>>> (the same origin resource of the bundle) from the specified bundle, instead
>>>>>>>>>>>>>>> of the network.
>>>>>>>>>>>>>>> <img src='https://www.exmaple.com/a.png'>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Is my understanding correct?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> On Fri, Aug 28, 2020 at 2:30 PM Ryosuke Niwa <
>>>>>>>>>>>>>>> rniwa@apple.com> wrote:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> On Aug 27, 2020, at 1:05 PM, Jeffrey Yasskin <
>>>>>>>>>>>>>>>> jyasskin@google.com> wrote:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Hi Web Perf experts,
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> We're working
>>>>>>>>>>>>>>>> <https://www.chromestatus.com/feature/5710618575241216> on
>>>>>>>>>>>>>>>> using (unsigned) web bundles to help with preloading subresources. The
>>>>>>>>>>>>>>>> current design is at
>>>>>>>>>>>>>>>> https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md,
>>>>>>>>>>>>>>>> but roughly the idea is that a page would build a bundle of the
>>>>>>>>>>>>>>>> subresources it intends to use and put a
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> <link rel="webbundle" href="/the_bundle.wbn"
>>>>>>>>>>>>>>>> scope="/resources">
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> with their other preloads (or one of several variations).
>>>>>>>>>>>>>>>> After that,
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> <script src="/resources/foo.js">
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> would find the version in the bundle instead of having to
>>>>>>>>>>>>>>>> fetch it independently.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> This isn’t about preloading is it? This will actually
>>>>>>>>>>>>>>>> affect the resource being used by that script element. preload doesn’t do
>>>>>>>>>>>>>>>> that so this is a pretty different feature.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> In https://github.com/WICG/webpackage/issues/580,
>>>>>>>>>>>>>>>> Krzysztof worries that adding any new way for a <link> tag to affect script
>>>>>>>>>>>>>>>> loading is a security risk, because pages may not be as careful about
>>>>>>>>>>>>>>>> preventing users from injecting <link> tags as they are about <script>
>>>>>>>>>>>>>>>> tags. Instead, he suggests using a Javascript API to tell the browser to
>>>>>>>>>>>>>>>> preload subresources using a bundle.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> That would be a pretty serious security risk. Putting all
>>>>>>>>>>>>>>>> other objections against web packaging / web bundles aside, this will be a
>>>>>>>>>>>>>>>> pretty big show stopper.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> - R. Niwa
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> --
>>>>>>>>>>>>>>> Hayato
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> --
>>>>>>>>>>>> koto@ / Krzysztof Kotowicz / Google
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> --
>>>>>>>>>> koto@ / Krzysztof Kotowicz / Google
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>> --
>>>>>>>> koto@ / Krzysztof Kotowicz / Google
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>> --
>>>>>> Hayato
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Hayato
>>>>>
>>>>
>>>>
>>>> --
>>>> koto@ / Krzysztof Kotowicz / Google
>>>>
>>>
>>
>> --
>> koto@ / Krzysztof Kotowicz / Google
>>
>

-- 
Hayato

Received on Friday, 25 September 2020 02:17:55 UTC