Re: Preloading using JS instead of a tag

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.

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
>

Received on Friday, 18 September 2020 18:04:55 UTC