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

Proposal: Define new feature types #19

Closed
clelland opened this issue Feb 20, 2019 · 13 comments
Closed

Proposal: Define new feature types #19

clelland opened this issue Feb 20, 2019 · 13 comments

Comments

@clelland
Copy link
Collaborator

Following up on the discussion in w3c/webappsec-permissions-policy#252, I think it may make sense to identify the different types of features in the web platform, and define different strategies for how they should be handled as policy-controlled features.

The current mechanism for declaring these strategies is the default allowlist, which isn't actually an allowlist, but one of three special values. These values define the default availability and the inheritance strategy for the features which use them; we should be able to define new strategies, while still keeping within the spirit of the original design.

In offline discussions, we've identified at least these types of features:

  1. Permissions and Powerful Features (current default allowlist: 'self')
    • Examples: Fullscreen, PaymentRequest, Geolocation, Camera, Accelerometer
    • These need to be denied by default across origin boundaries, but should be available to top-level pages.
  2. Performance Best Practices / Interventions (current default allowlist: *)
    • Examples: unoptimized-images, unsized-media, layout-animations
    • These generally only need to apply to the document that sets the policy, and there is little benefit to forcing the policy on subframes.
  3. Sandbox features (current default allowlist: *)
    • Examples: top-navigation, scripts, popups, presentation, forms, pointer-lock, modals
  4. Hopeful deprecations (current default allowlist: *)
    • Examples: document-write, document-cookie, document-domain
    • These all have the property that, while we'd like to remove them from the platform, or replace them with faster or async versions, arbitrarily imposing them on a subframe may have unintented consequences in that frame.

There may be more, but hopefully not too many.

I think that we can replace the existing "default allowlist" concept with something more like an "inheritance strategy". We can remove the unused 'none' value and define an initial set of four strategies:

  1. Permissions and Powerful Features

    • Allow in a top level browsing context.
    • Deny by default in cross-origin subframes.
    • Cannot be reenabled if disallowed by the inherited policy
    • Treat popups as children of the page that opened them, unless the popup disowns its opener (to prevent a leak where a restricted frame spawns a new window to use the feature and communicate back. (#173))
    • These are all boolean flags. A feature is either allowed or not in any given frame.
  2. Performance Best Practices

    • Default state in any browsing context is to make no change to the web platform.
    • Can be set/cleared as necessary in each document. (No inheritance in subframes)
      • In most circumstances, performance issues in subframes do not affect the embedding frame
    • These features may start taking on parameters; they are more subtle than (1), above. (See Proposal: Parameterized features w3c/webappsec-permissions-policy#163)
  3. Sandbox features (#74)

    • Allow in a top level browsing context.
    • Allow by default in subframes, but can be disallowed explicitly.
    • Cannot be reenabled if disallowed by the inherited policy.
    • Deny by default in a frame with the 'sandbox' attribute, unless explicitly allowed. (See doc)
    • If denied in a frame, also deny in its popups, unless it is allowed the feature 'popups-escape-sandbox' (for backwards compatibility)
    • These are all boolean flags. A feature is either allowed or not in any given frame.
  4. Hopeful deprecations (bikeshedding for a better name needed)

    • Allowed by default in all frames (not inherited by subframes by default)
    • Can be denied in any frame with a Feature-Policy header
    • Can be denied in a subframe with the allow attribute, but the loaded document must have a Feature Policy header which accepts that restriction, or else a network error will be triggered.
    • These are all boolean flags. A feature is either allowed or not in any given frame.
@clelland
Copy link
Collaborator Author

@annevk @bzbarsky @jyasskin @martinthomson @ojanvafai FYI, any comments or bikeshed discussions welcome :)

@martinthomson
Copy link

I think that these are the things you have in mind. I see the "permissions" group as being most urgent for Mozilla, with varying degrees of value for the others.

The important point here is that we see this as being guidance not just on how to deal with features generally, but also on the technical manifestation of the controls. That is, there might be a different implementation for each of the categories, with different means of controlling the feature. Categorizing in this way should make it easier to make appropriate choices about what mechanisms are used to support each.

For example, with permissions, the most important thing for us is providing a way for a page to set the inherited permissions for sub-frames. The complicated machinery in this proposal with a rich policy language and HTTP header field is not necessary to support that.

What are your plans with CSP here?

@triblondon
Copy link

I'm slightly uncomfortable with making the categorical distinctions outlined here. If the policy mechanism is different for some policies vs others, on an abstract point such as whether the policy decision permeates iframes, that makes the whole thing quite difficult to reason about, unless we were to split feature policy into multiple separate standards.

In my mind the best practices / antipatterns flags are not just for site owners' benefit - as a developer I might reasonably want to enforce no document-write API for third party subframes, for example, and get reports when subframes violate those policies.

It's the best practices / deprecations flags that are most exciting about Feature policy for me, and I'm keen not to see these get too complicated, otherwise I think we risk substantially reducing adoption.

In relation to @martinthomson's point, it's my understanding that the vast majority of foreign origin subframes are created by third party scripts that execute in the root document. Therefore, is solving the problem of inheritance of permissions for subframes really possible without setting policy on the root document?

@annevk
Copy link

annevk commented Feb 25, 2019

I think it actually makes sense to indeed split these into different features as you suggest @triblondon. I'm not sure about 2 and 4, but for permissions and sandboxing I have some thoughts:

  • Permissions: it seems to me this should not inherit into an auxiliary browsing context (popup). You can delegate the permission for getting access to geolocation to a nested browsing context (subframe), but not a popup. A popup has its own address bar for the user to blame. The moment you talk about restricting such a popup as well it is a sandboxing feature (i.e., a restriction).
  • Sandboxing: unless it's one of the types of sandboxing we already allow, I think we should have an explicit opt-in negotation with those being sandboxed. We should not allow embedders to decide the control flow beyond the extent to which they already have that ability. And we should probably also enable embeddees to protect themselves against existing forms of sandboxing (by turning into a network error if something is imposed upon them they do not like).

Permission capabilities are useful to allow the first-party to enable a third-party subframe to ask something from the user on behalf of the first-party.

Sandboxing capabilities are useful to allow a first-party to impose restrictions on a third-party the third-party cannot get out of (i.e., not even via an allow-popups popup). And new restrictions are done via negotiation so third-parties cannot unwittingly have their control flow altered.

@triblondon
Copy link

Agree on the URL bar thing. If it has a visible domain, it should be able to make its own way in the world of policy.

Disagree on the distinction - If we can model all policies in the same way, we should, and the standard will be more powerful for it.

@annevk
Copy link

annevk commented Feb 26, 2019

You cannot have both given the status quo on sandboxing.

@clelland
Copy link
Collaborator Author

@annevk, What you're saying about permissions makes some sense -- maybe they are categorically different from powerful features, since the point is all about delegating the ability to ask the user for permission, rather than just the ability to use the feature. In general, I don't think we want to allow popups to be a way to circumvent policies, but in this case, it seems right -- at least if the URL bar is visible. I'll see if I can get some security UI folks to chime in.

  • Sandboxing -- I agree that new restrictions, unless there is already a well defined, expected failure path, are going to need opt-in. And like embedded-CSP, not opting in just means that you don't get to be embedded.

The distinction between things which are normally allowed (sandbox, antipatterns) and normally disallowed (permissions in cross-origin frames) is a useful one.

@jan-ivar
Copy link

I don't think we want to allow popups to be a way to circumvent policies, but in this case, it seems right

I think that’s because a permission is more than the absence of a restriction to be circumvented. It’s a delegation of user trust not otherwise available through escape to some baseline.

I think our reverse framing of restrictions as allowances—though I appreciate the benefits of this—helps blur the distinction between restrictions (on baseline privileges) vs. elevated origin-tied privileges not normally extended across top-level origins, e.g. to popups.

Whether an API that leverages this overlap is a good one or a bad one, I think is the debate. I'm open to mentally taxing implementers, as long as the leaky abstraction does not lead to user error.

@annevk
Copy link

annevk commented Apr 24, 2019

@clelland and I discussed this further offline, taking into account some new ideas at Google and Mozilla, and the rough plan is to split FP into 3 pieces:

  • Delegating permissions: this reuses the existing allow attribute and semantics, but the set of features will be restricted to those that have to do something with permissions where the browser might conceivably ask the user, including such things as <input type=file>. The expectation here is that the "permission" feature is disabled in the third-party context and therefore allow makes a lot of sense to enable it. (TBD: corresponding header, API.)
  • Document sandboxing: this is about imposing restrictions on yourself, e.g., for better performance or less weird behavior of code, e.g., disabling the named getter on the global object. This only applies to the document the header is set for and any documents that document creates through about:blank, blob/data URLs. (As otherwise those could be used as escape hatches.)
  • Full sandboxing: this should have parity with the sandbox attribute, including reusing its infrastructure, except that it starts from the empty set and builds up from there. In addition, as this can alter the code flow of third parties, they'll have to opt-in via a request/response header protocol for any newly added sandboxing flags. The existing sandboxing features of sandbox will not require opt-in (though we should probably start sending out the request header for them so sites have more control).

Note that Document and Full sandboxing will not allow for per-origin control over features. Document sandboxing applies to the current Document only and Full sandboxing applies to all origins that end up in a sandboxed browsing context.

@triblondon
Copy link

This seems like a reasonable idea. I don't feel that excited about it, mainly because it's a lot of complexity and wiring for developers to adopt, but also more practically because it seems to eliminate a couple of useful use cases, such as imposing deprecated feature restrictions on third parties. For example is setting document.domain a document sandbox thing or a full sandbox thing? Or might some features be available via both mechanisms?

@annevk
Copy link

annevk commented Apr 29, 2019

Some might be both. Ultimately it should be the same amount of complexity or less, but some of the complexity is more directly visible this way and not hidden behind a boolean implicitly associated with a feature policy string.

@clelland
Copy link
Collaborator Author

I've proposed a slightly different version of this, explainer-style, in w3c/webappsec-permissions-policy#328; basically covering document sandboxing and full sandboxing, for a common set of features. Developers would have the ability to specify whether they wanted to restrict just themselves, just certain subframes, or both.

If we move that direction, then the existing spec would cover the feature delegation case, for permissions and other features which are enabled for top-level documents, and need to be delegated to third parties. Based on discussions with folks, and on the feature survey in w3c/webappsec-permissions-policy#296, I'm convinced that those features are a different kind than the document-configuration or sandboxing-style features.

@clelland
Copy link
Collaborator Author

Closed with the introduction of Document Policy to handle the non-permissiony, non-powerful-feature model. Document Policy handles the two sandboxing mechanisms mentioned here, the performance-best-practices, and probably the hopeful deprecations.

@clelland clelland transferred this issue from w3c/webappsec-permissions-policy Dec 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants