Re: Preloading using JS instead of a tag

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. 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

Received on Monday, 21 September 2020 14:53:51 UTC