Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TAG review for web app scope_extensions #875

Open
diekus opened this issue Jul 20, 2023 · 51 comments
Open

TAG review for web app scope_extensions #875

diekus opened this issue Jul 20, 2023 · 51 comments
Assignees
Labels
Progress: in progress Review type: CG early review An early review of general direction from a Community Group Venue: WICG

Comments

@diekus
Copy link

diekus commented Jul 20, 2023

Hola TAG!

I'm requesting a TAG review of scope-extensions.

This document describes a new scope_extensions manifest member that enables web apps to extend their scope to other origins. This allows sites that control multiple subdomains and top level domains to behave as one contiguous web app and also enables web apps to capture user navigations to sites they are affiliated with.

  • Explainer¹ (minimally containing user needs and example code): Scope Extensions explainer
  • Specification URL: N/A
  • Tests: N/A
  • User research: N/A
  • Security and Privacy self-review²: url
  • GitHub repo (if you prefer feedback filed there): url
  • Primary contacts (and their relationship to the specification):
  • Organization(s)/project(s) driving the specification: Microsoft (Edge)
  • Key pieces of existing multi-stakeholder review or discussion of this specification: N/A
  • External status/issue trackers for this specification (publicly visible, e.g. Chrome Status): ChromeStatus entry

Further details:

  • [ X ] I have reviewed the TAG's Web Platform Design Principles
  • Relevant time constraints or deadlines: [please provide]
  • The group where the work on this specification is currently being done: WICG
  • The group where standardization of this work is intended to be done (if current group is a community group or other incubation venue): WICG
  • Major unresolved issues with or opposition to this specification: N/A
  • This work is being funded by: Microsoft

You should also know that...

[please tell us anything you think is relevant to this review]

We'd prefer the TAG provide feedback as (please delete all but the desired option):

💬 leave review feedback as a comment in this issue and @-notify [luhuangmsft and diekus]

@torgo torgo added Review type: CG early review An early review of general direction from a Community Group and removed Progress: untriaged labels Aug 30, 2023
@torgo torgo self-assigned this Aug 30, 2023
@torgo torgo added this to the 2023-09-04-week milestone Aug 30, 2023
@alancutter
Copy link

@torgo
Copy link
Member

torgo commented Sep 7, 2023

Hi @diekus – Thanks for sending us this. Briefly, we're concerned about the way that this proposal changes the same-origin model, which is a fundamental part of the security apparatus of the web. Hence we think we need to tread very carefully. We think the explainer should be very explicit about what the expanded scope does and does not allow access to. We'd also like to see some specific use cases and discussion of abuse cases (and how those abuse cases are mitigated). E.g. if you are tricked into visiting or downloading a malicious app that is spoofing your bank, and it includes your bank's origin in its scope_extensions field, are there additional exploits that the malicious party could exploit (e.g. obtaining credentials or capturing links)? Are there any implications for access to local storage from different origins?

@LuHuangMSFT
Copy link

LuHuangMSFT commented Sep 28, 2023

@torgo Discussed with @diekus and below are our thoughts. I'll organize the important parts and add to the explainer. Thanks for your feedback.

  • Storage and permissions models are unaffected by this proposal and should remain so.
  • In Chromium, there are 2 behaviors we are working on in the near term that will be able to influenced by scope_extensions. These are essentially UX treatments.
    • Web app windows will not display out-of-scope UI when navigating within extended scope
    • Links to extended scope can cause the app window to launch

To prevent spoofing attacks, the implementation in Chromium will flash the web origin of the content in the window title bar after every top level navigation. The origin information will also be visible in the app's main menu.

If the user is tricked into visiting or installing a malicious app that is spoofing my bank

  • they can already do this without scope_extensions
  • if the malicious app includes my bank's origin in scope_extensions but my bank does not validate the association, my bank's content will appear with out-of-scope UI, and won't share any storage or permissions regardless. This is no different that if the malicious app simple redirected to my bank's site.

To use scope_extensions, the owner of the app should either also directly own/control the listed origins in scope_extensions or monitor them closely if working by agreement with parties that own them.

Browser security tools such as Microsoft Defender SmartScreen should still identify unsafe origins that are navigated to from the app window.

@torgo torgo modified the milestones: 2023-09-04-week, 2023-10-09-week, 2023-10-16-week Oct 8, 2023
@ylafon
Copy link
Member

ylafon commented Oct 10, 2023

Hi, we discussed the issue during our breakout today.
Could there be cryptographic proof that the added origins are agreeing to being embedded in that web app.
Pretty much like Universal Link or App Link?

@LuHuangMSFT
Copy link

LuHuangMSFT commented Oct 10, 2023

The apple-app-site-association file used by Universal Links references apps by an appID string of the format <Application Identifier Prefix>.<Bundle Identifier>. [1] I don't see usage of a cryptographic hash. Please correct me here if I'm missing something.

assetlinks.json, used by Android App Links, refers to apps by an app id and SHA256 fingerprints of the app's signing certificate. [2]

Use of a unique app id [3] should be sufficient evidence that the added origins are agreeing to being embedded in that uniquely identified web app. In the scenario where the app is signed or delivered as an immutable package, use of a cryptographic hash would be useful to further specify that the association is only valid when the app is unchanged. Being able to specify that the app remain unchanged doesn't seem like a useful feature for web apps with frequently changing content served through the web.

One scenario we should consider: if the web app is taken over by another party which does not have access to the original signing certificate, they would be unable to modify the app and produce cryptographic evidence matching the original - thus the origin association would become invalid.

The dominant method of delivery of web apps is over the web and managed by a browser without signing or packaging/bundling. Referencing web apps by unique app id is an acceptable solution that doesn't significantly complicate the steps developers need to take to set up the association.

To mitigate app takeover issues (where app ownership changes), we recommend that the web app and associated origins are owned and controlled by the same entity. Failing that, both the app and associated origins are advised to monitor ownership and condition of their counterparty.

[1] https://developer.apple.com/documentation/xcode/supporting-associated-domains
[2] https://developer.android.com/training/app-links/verify-android-applinks#web-assoc
[3] https://github.com/philloooo/pwa-unique-id/blob/main/explainer.md#requirements

@alancutter
Copy link

Could there be cryptographic proof that the added origins are agreeing to being embedded in that web app.

Is it sufficient that the added origin explicitly grants the web app permission in a file hosted on the origin served over HTTPS?

@ylafon
Copy link
Member

ylafon commented Oct 17, 2023

In the case of apps, the verification of app links is done by the store owner, in the case of a web app, you need to have verification done in another way. This is similar to the origin issue in MiniApps Having something hosted on the origin server might work, but it would require network access.

To mitigate app takeover issues (where app ownership changes), we recommend that the web app and associated origins are owned and controlled by the same entity.

controlled in legal term (in which jurisdiction?) or in technical terms (as same hosting)

@LuHuangMSFT
Copy link

LuHuangMSFT commented Oct 17, 2023

Controlled in practical terms - as it requires some level of control over the domain to be able to add /.well-known/ configuration. What's an appropriate way to phrase that in spec language?

@ylafon
Copy link
Member

ylafon commented Nov 20, 2023

Well, the site has to agree that a web app can impersonate its content, so it is more than putting one file and be done (as other web apps could rely on its presence and do the same), there need to be something along the line of what is done in the ACME protocol, or else, in the case of offline web apps, a way to check this offline.

@alancutter
Copy link

alancutter commented Dec 1, 2023

as other web apps could rely on its presence

The site identifies a particular web app to associate with via the web app's manifest id, other web apps will be excluded by this.

in the case of offline web apps, a way to check this offline.

Does "offline" mean offline at all stages even during installation? A fully offline web app should probably be built as an IWA rather than use any HTTPS.

@torgo
Copy link
Member

torgo commented Aug 7, 2024

Hi @LuHuangMSFT - following on from what @martinthomson said above: as noted we are fine with the user need and we are generally fine with the design. @reillyeon has suggested a CORS or CORS-like approach. Whilst that has some advantages (in particular, not requiring a new well-known located file) it also has the disadvantage of requiring complex server configuration. Our main concern stands, however, that the Association file should allow for more specifying resources in a more fine-grained way. This could include wildcards to make it easy to create a very permissive Association file, but it should be possible to lock down the resources that are OK to share. Would you be OK with modifying the design to allow for such an approach? If so, we're happy to close this review as satisfied.

@torgo torgo modified the milestones: 2024-08-05-week, 2024-08-12-week Aug 8, 2024
@torgo torgo added the Progress: propose closing we think it should be closed but are waiting on some feedback or consensus label Aug 14, 2024
@LuHuangMSFT
Copy link

LuHuangMSFT commented Aug 14, 2024

Update: I am investigating making 2 modifications to the design.

  1. For the case where the same-site format is used in the web app manifest to include a dynamic number of origins, add an additional requirement that response headers from an origin must include the manifest IDs of apps it agrees to be part of.

  2. Allow sites/origins to provide a 'scope' filter in their association files in .well-known path. This allows controlling resources using the same syntax as what is used in manifest scope.

I will update with more details after my investigation is complete.

@LuHuangMSFT
Copy link

Specifying scope in the association file

I've looked at the following options to give the association file a way to specify resources explicitly. My preference is for the fallback list. It's more verbose but allows us to accept URLPattern (or other formats) in the future. UAs are able to fall back to a simpler format following a clear order if they are unable to process a more complicated format. If left unspecified, the whole origin/site is considered part of the identified app with no resource restrictions.

Bag of things 1

{
  "web_apps": [
    {
      "web_app_identity": "https://myapp.com/index.html",
      "scope": "/app",  // Can be string or array of strings.
      "scope_url_pattern": "https://this-origin.com/?"  // Can be string or object.
      // Extend here.
    }
  ]
}

Bag of things 2

{
  "web_apps": [
    {
      "web_app_identity": "https://myapp.com/index.html",
      "scope": {
        "prefix": "/app",  // Can be string or array of strings.
        "url_pattern": "https://this-origin.com/?" // Can be string or object.
        // Extend here.
      }
    }
  ]
}

Fallback list

{
  "web_apps": [
    {
      "web_app_identity": "https://myapp.com/index.html",
      "scope": [
        {
          "url_pattern": "https://this-origin.com/?"  // Can be string or object.
        },
        {
          "prefix": "/app",  // Can be string or array of strings.
        }
        // Extend here.
      ]
    }
  ]
}

@LuHuangMSFT
Copy link

LuHuangMSFT commented Aug 20, 2024

Request and Response Header

For multiple sub-domains included from the web app manifest using a same-site entry, we can make use of a request and response header design with no preflight. This allows an origin that was included via the same-site manifest entry to confirm its participation. This doesn't require an association file to be fetched immediately before fetching the resource and would not slow down navigation. This is largely what @reillyeon described above.

Example:

App window navigates to https://foo.com

  • Request contains App-Id: https://myapp.com/index.html header.
  • Response contains App-Scope-Extension-Allow-Id: https://myapp.com/index.html, https://otherapp.com/index.html

The resource can load in the app window without warning UI or being moved to a tab. The response can be App-Scope-Extension-Allow-Id: * to match all app ids. If the app id does not match or there is no matching response, the resource is not treated as part of the app.

The server can either configure a static list of app ids for simplicity or dynamically control the value of App-Scope-Extension-Allow-Id and use this to implement scoping.

@torgo
Copy link
Member

torgo commented Aug 29, 2024

Hi @LuHuangMSFT thanks for this - we're just reviewing in our TAG plenary call today and we're going to get back to you after we have a chance to think about / discuss more deeply.

@dmurph
Copy link

dmurph commented Aug 29, 2024

Question - do we need to have the initial App-Id header? Can we only have the second one? The implementation of that seems possibly infeasible.

@martinthomson
Copy link
Contributor

So I think that the requirement needs to be that the browser needs to know whether something is in app scope before navigating. Any solution that involves finding out at the time is going to introduce latency penalties that are undesirable.

For me, that rules out anything that is exclusively CORS-like. Navigation is commonplace and adding an extra round trip to all navigations from an app isn't a great outcome, even if it is only for cross origin navigations (we don't need to add that barrier structurally, even if a lot of applications insist upon it).

However, it isn't quite that simple. The app lists what it thinks is in scope, so the point of this design is to confirm. We would start from an assumption that the app is making a correct representation, then confirm that with the app. That isn't CORS-like, that's something new (-ish, the introduction of Sec-Fetch-Dest is somewhat of a confirmation stage, as are some of the other CORS headers that determine whether a response is readable).

So I'm of two minds here. I hate the constant addition of stuff to HTTP requests. It's really starting to get out of hand (especially with very long field names, the risk that requests exceed the size of a packet is real and that has serious performance implications). But Reilly's suggestion has real merit. I also see the advantages of following that model of confirmation.

@dmurph's concern about two fields is easy to answer, I think: the site likely needs to know who is asking before they answer. Because the answer could depend. Sites could have resources that are acceptably included in multiple apps.

The manifest-like approach is also reasonable. A centralized location where you can interrogate an origin about the scopes that can extend to it is OK. I find myself horrified at the complexity of the proposals though. Please, if we go that way, can we focus on what is the minimum possible syntax that will achieve the desired outcome. This works:

{
   "https://example.com/this-is-an-app/": ["/payments", "/anti-fraud-stuff"],
}

(Yes, it is not extensible, but it is replaceable and that is enough.)

However, throwing out ideas is not what we need here. What is needed is to ask one question: What is the form of this that site operators are best able to handle?

@dmurph
Copy link

dmurph commented Sep 4, 2024

From a chat with @LuHuangMSFT and a member of our security team, here is a proposal they were comfortable with. Not sure if this is something you're still OK with @LuHuangMSFT:

There are three levels of security for this association:

  1. None (not used)
  2. The .well-known/scope-extensions file acknowledgement on the extended origin/site.
    • If the origin/site doesn't have the manifest_id in that file, the association isn't created.
    • This can be re-checked periodically, allowing removal of associations but sometimes delayed.
  3. Both a .well-known/scope-extensions file acknowledgement on the extended origin/site AND a ScopeExtensionAllowed: <manifest_id_list> response headers coming from 'extended' sites or origins.
    • If the user agent ever does not receive this header from the server, then it removes the association. (Recoverable through existing manifest update mechanism if this was a dev mistake).
    • This allows a site/origin owner to immediately remove this association.

For origin type scope extensions, this requires level 2 security.
For site type scope extensions, this requires level 3 security.

Reasoning:

  • None of these impede navigation / would affect performance.
  • The information is always known at install-time.
  • The origin case is more common for smaller developers & remains easy to do & set up - no need to muck with network neaders.
  • The site case is more complex & requires a more complex system that is likely a larger organization anyways, so setting that up to always include the correct response header seems OK.
  • The App-Id header seems not necessary - This only seems necessary if the site is expecting to have a very large list of apps extending to it, so it doesn't want to have a large network response. There have been no use-cases that we know about that require this or match this behavior. Also - this would be very hard to implement.
    • If needed in a future, then this can still be added.

Note this is separate from the filtering discussions, just for security here. Filtering can be handled by the current proposals with the .well-known/scope-extensions file and manifest file.

@LuHuangMSFT
Copy link

LuHuangMSFT commented Sep 4, 2024

Thanks @dmurph. That's representative of what we discussed in that meeting. It is good solution that does not require a request header and I agree with the tiered approach for origin vs. site extension, as well as the reasoning bullet points.

App-Id is not necessary if the response header returns all manifest IDs that the origin recognizes.
For completeness, I want to point out that not implementing an App-Id request header will not allow the server to control filtering differently for different origins. The filtering information (paths, URLPattern, etc.) will be in the association file and the same information will be applied to all origin matching a site extension.

Since

  • Per origin filtering when using a site extension is not a requirement for the known use cases, and
  • Nothing prevents App-Id from being specified in the future if the need arises, and
  • It would be easier for site operators to configure,

only requiring a response header with manifest IDs for site extension case is my preference.


Other issues

  • We can find a shorter name for the response header field (Extends-Apps?)
  • Re. specifying minimal filtering syntax - will replacement instead of extension not cause compatibility problems?

@torgo torgo modified the milestones: 2024-09-02-week, 2024-09-09-week Sep 4, 2024
@martinthomson
Copy link
Contributor

@dmurph that sounds encouraging. I'm a little unclear on the site vs. origin thing, but rather than continue the discussion here, can I suggest that you take this back to the explainer and update that?

@LuHuangMSFT
Copy link

I'll make an explainer PR that should offer more clarity.

@martinthomson
Copy link
Contributor

Thanks for taking on the feedback. We understand that this is an early review and it will need some more work to integrate the changes. When you get things more settled, we'd be happy to do another view. Closing this for now.

@martinthomson martinthomson added Resolution: validated This is for early reviews where we largely support the direction the work is going in. and removed Progress: propose closing we think it should be closed but are waiting on some feedback or consensus labels Sep 11, 2024
@LuHuangMSFT
Copy link

@martinthomson
I have updated the explainer [1] significantly to incorporate feedback and move the contentious portion involving the header design out of scope (this portion will be rewritten as a new, additional explainer).

Could we re-open this review?

[1] https://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-explainer.md

@torgo torgo reopened this Nov 21, 2024
@torgo torgo removed this from the 2024-09-09-week milestone Nov 21, 2024
@torgo torgo added Progress: in progress and removed Resolution: validated This is for early reviews where we largely support the direction the work is going in. labels Nov 21, 2024
@torgo torgo added this to the 2024-12-03-f2f-Edinburgh milestone Nov 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Progress: in progress Review type: CG early review An early review of general direction from a Community Group Venue: WICG
Projects
None yet
Development

No branches or pull requests