Skip to content

Header should be sufficient in some cases to delegate features (esp. Client Hints) #408

@clelland

Description

@clelland

I think that the changes made in #378 may have gone a bit further than necessary. #357, which was the motivation for the change, asked that blocking policies set in the header not be overridable with the allow attribute.

#378 does this, by making policy inheritance essentially the logical AND of parent-header and iframe attribute policy, and necessarily switches the header defaults for every feature to "*". (That was necessary so that developers would not be required to set the header in order to enable delegation at all, but could use just the attribute in the common case.) This also ends up making the allow attribute required in every case to delegate any permission.

Unfortunately, this model breaks some deployed use cases, where the header could previously have been used to explicitly grant permission to specific origins, and isn't very ergonomic for the Client-hint delegation case, where not only would every hint need to be specified on every frame, but we lose the ability to tell from the header which hints should be sent with subresource requests.

@yoavweiss suggested in email a small tweak which would reenable the use case of "enable delegation for specific sites with the header" and would allow Client Hints to be delegated with the header only. It involves treating an explicit header declaration, where a feature is mentioned in the header, with an associated allowlist, differently from the 'default' behaviour when the feature is not mentioned at all in a header.

Thinking about this a bit, it seems to me that the current state of the allow attribute when it comes to Client Hints and iframe delegation is not something that most developers would be able to use.

Currently developers are required to add an Accept-CH header in order to be able to delegate Client Hints (which already multiple folks found confusing). If we add a Permissions Policy requirement on top of that, that is not likely to make things better.

The way most people delegate permissions is by providing developers with a snippet of HTML they can integrate into their site, including a list of allow values. Asking them to muck around with headers is completely orthogonal to this flow, and doesn't serve much when it comes to the goal of CH being "accountable". The browser can keep track of an allow attribute in exactly the same way it can keep track of a header-based opt-in.

That that end, I propose:

  • To change Client Hints' delegation model so that an Accept-CH opt-in will not be required in order to be able to delegate hints to a header.
  • To change Permission Policy so that explicit restrictions are different than default restrictions
    • We want explicit restrictions to not be overridable, but implicit (by default) restrictions should be overridable.
    • That way, CH are handled correctly, without special-casing them.

I want to propose a change which would allow this, as well as the existing use cases, while still being web-compatible:

  • Header allowlist is 'default' unless otherwise specified. Iframe allowlist is 'default' unless otherwise specified.
  • Powerful features (currently "default 'self'") and high-entropy client hints:
    • Grant access to this document if header allowlist doesn't explicitly exclude 'self'
    • Grant access to same-origin frames if this document has access, and iframe allowlist doesn't explicitly exclude 'self'.
    • Grant access to cross-origin iframes if:
      1. This document has access,
      2. Either header or iframe allowlist explicitly includes its origin, and
      3. Neither header nor iframe allowlist explicitly excludes its origin.
  • Other features (syncxhr?) and low-entropy client hints ("default *"):
    • Grant access to this document if header allowlist doesn't explicitly exclude 'self'
    • Grant access to same-origin frames if this document has access, and iframe allowlist doesn't explicitly exclude 'self'.
    • Grant access to cross-origin iframes if:
      1. This document has access, and
      2. Neither header nor iframe allowlist explicitly excludes its origin.

We can do this with a simple change to the Define an inherited policy for feature in container at origin algorithm, inserting this step between what is currently steps 5 and 6:

If feature is present in policy’s declared policy, and the allowlist for feature in policy’s declared policy matches origin, then return "Enabled".

I have tested a Chromium CL with this, which passes all existing Feature-Policy tests, except for those which expose the new "Should be irrevocably blocked by the header" behaviour, but that is the behaviour that we want in any case, so those test expectations should be updated to match.

I'll work up a PR to add this, as well.

Opinions welcomed :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions