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

Permission policy system after the OT #558

Closed
alois-bissuel opened this issue Sep 16, 2022 · 20 comments · Fixed by #713
Closed

Permission policy system after the OT #558

alois-bissuel opened this issue Sep 16, 2022 · 20 comments · Fixed by #713

Comments

@alois-bissuel
Copy link
Contributor

Hello,

During the OT, the permission policy system has been lifted for easier testing (#551, see our related ask in #519 and in the ps-dev-support).
I am now wondering about the end state of the API if it graduates after the OT.

If the permission policy system is to be kept as is (ie the standard delegation system), there is a high probability that some of our inventory won't have access to the API. Ads may be rendered in nested iFrames dropped by transient actors (eg for AB-testing or other purposes), who may not delegate the permission.

Do you see any solution to this kind of issue?

P.S. Linking #393 as it already lists various arguments for the default permission policy.

@csharrison
Copy link
Collaborator

Thanks @alois-bissuel for filing. I chatted with @clelland about this briefly in TPAC because it seems like a legitimate concern. Let me summarize how I am thinking about this:

  1. We want some level of opt-in for the APIs in third party contexts, to ensure that sites have control over who can measure their user's cross site activity. This is also important for things like rate limits where we don't want evil iframes consuming any kind of "budget".
  2. The kind of opt-in that Permissions Policy asks for is very heavyweight, because it requires a whole tree of frames to opt-in to their children having the permission.
  3. In the real world, it is common for transient frames to pop in and out of existence in the course of ads serving, and it is a large coordination problem to ensure that the whole tree is decorated correctly with the right permissions. One badly configured / buggy frame will cause the API to be disabled.

After thinking about it for a bit I thought of a potential middle ground policy we might want to consider: a way for frames to set a policy on a child and allow it to recursively propagate:

<iframe src="..." allow-recursive="attribution-reporting"></iframe>

Concretely, the recursively allowed features would be inherited by a subframe, and also propagated to that subframe’s children (and so on). Possibly, it could also be applied to documents the frame navigates to e.g. in redirects?

The biggest challenge with a relaxed permission like this is that it could be surprising to a frame not expecting a recursive permission to be applied (e.g. one that embeds untrusted content). To prevent security issues from silently propagating permissions, we would need to ensure that frames understand what is happening and what their recursive policy is, e.g. via HTTP headers or JS accessors. They should similarly be able to revoke the recursive policy with those same mechanisms (response headers, JS API).

Anyway, I’m still not sure how I feel about a proposal like this but I’d be curious to understand if it would solve the issues you mentioned, @alois-bissuel. My thinking is that this is strictly better than a default of * because:
a. Default * requires all publishers and frames to opt-out if they don't want children using the API
b. Default self with allow-recursive mechanism requires all embedded frames to opt-out if they don't want children using the API.

(b) is a strict subset of (a), so we'd be reducing the number of parties needing to explicitly opt-out.

cc @maudnals

@alois-bissuel
Copy link
Contributor Author

Thanks for the detailed answer.
It looks like it would indeed solve our use case, depending on the default permission being discussed in #393.

@zhengweiwithoutthei
Copy link

with (a) I am not sure if it is true that default * requires all frames to opt-out if they don't want children to use the API. My understanding is the opt-out with header is recursive in nature. For example, if a publisher opt-out with header Permissions-Policy: attribution-reporting=(), the API is disabled on the publisher's document as well as any child frame.

(b) self + "allow-recursive" basically turn any nested frames into the case of (a). It does provide some flexibility for publisher to opt-in itself and the frames they truest but disable the API on the others.

@jfggit
Copy link

jfggit commented Jan 9, 2023

I just want to chime in here to echo the concern with the existing permissions policy behavior. As mentioned, there can be an entire chain of iframe ancestors owned by parties who may be 1) unknown, 2) ephemeral, 3) unwilling or uninterested in propagating permissions downstream, against the preferences of the top-level site owner.

Although in reading these permissions-policy docs, it reads like even if the default policy is attribution-reporting=*, we would still need allow="attribution-reporting" on every iframe in order to actually propagate that permission. Is that accurate to the current state of the OT? Similarly, if post-OT, a publisher were to mark their top-level page with Permissions-Policy: attribution-reporting=*, would that setting also be limited by a lack of allow attributions on containing iframes?

Or, for a more targeted example, if publisher.com explicitly wants to allow a particular buyer (partneradtech.com) to measure on its domain, even when intermediary sellers are involved, there's no way to do that. If publisher.com returns headers Permissions-Policy: attribution-reporting=(partneradtech.com), partneradtech.com iframes would still only have permission if running as a direct child of the top page. Otherwise any intermediary iframes without allow attributes on them would block this permission propagation. Is that correct?

@csharrison
Copy link
Collaborator

with (a) I am not sure if it is true that default * requires all frames to opt-out if they don't want children to use the API. My understanding is the opt-out with header is recursive in nature. For example, if a publisher opt-out with header Permissions-Policy: attribution-reporting=(), the API is disabled on the publisher's document as well as any child frame.

The scenario where the publisher has no policy and the embedded frame does not want to propagate permission, the allow-recursive solution does not require the frame to act (as it does not have permission), whereas the default * does require the frame to act.

(b) self + "allow-recursive" basically turn any nested frames into the case of (a). It does provide some flexibility for publisher to opt-in itself and the frames they truest but disable the API on the others.

Yeah I agree with that, it's a good framing.

Although in reading these permissions-policy docs, it reads like even if the default policy is attribution-reporting=, we would still need allow="attribution-reporting" on every iframe in order to actually propagate that permission. Is that accurate to the current state of the OT? Similarly, if post-OT, a publisher were to mark their top-level page with Permissions-Policy: attribution-reporting=, would that setting also be limited by a lack of allow attributions on containing iframes?

This is not the behavior of the current OT, as a default value of * will allow children to use the API without allow. You can see the permissions policy spec for details (9.9.4):
https://www.w3.org/TR/permissions-policy-1/#algo-is-feature-enabled

That being said, your understanding is correct if the default is moved to "self". In that case, even the publisher declaring * does not automatically allow all iframes to use the API. I think that spec link also confirms this.

Or, for a more targeted example, if publisher.com explicitly wants to allow a particular buyer (partneradtech.com) to measure on its domain, even when intermediary sellers are involved, there's no way to do that. If publisher.com returns headers Permissions-Policy: attribution-reporting=(partneradtech.com), partneradtech.com iframes would still only have permission if running as a direct child of the top page. Otherwise any intermediary iframes without allow attributes on them would block this permission propagation. Is that correct?

That's correct if the default is moved to "self".

@jfggit
Copy link

jfggit commented Jan 11, 2023

Ah, so I think the part that I missed here is that there is a difference between a default value of *, and an explicitly set value of * from the top level page. The "* as default" scenario means allow-based propagation is unnecessary, whereas any other default value means allow-propagation is required and the Permissions-Policy header only serves as a mechanism to additionally restrict permission, not to grant it.

@csharrison
Copy link
Collaborator

@jfggit yes that's my understanding (I agree it is kind of confusing). My guess is that most of the docs you read were implicitly assuming a default value of "self", since * is fairly rare. cc @clelland

@jfggit
Copy link

jfggit commented Jan 11, 2023

Good to know and it would be great to get confirmation, as I was definitely confused here.

Ok, so then with this understanding, I think if "self" ends up as the default, allow-recursive would be potentially helpful, but probably not addressing a good chunk missing coverage. In the simplest and probably most common case, one or more of the "main" ad techs used by the publisher for filling ad space doesn't know or doesn't care about attribution reporting. As the top-most frame in any iframe chain for loading ads, if they don't set allow, it's not going to matter what anyone downstream does. From what analysis we've done, I think this is a significant fraction of our overall traffic.

@csharrison
Copy link
Collaborator

@jfggit I understand it is a large migration from the status-quo to use allow-recursive, but in the steady state I think most SSPs will be familiar with the API and will want to enable it. Or at least, that's my hope.

That being said, I agree that it isn't a perfect solve that gives as much coverage as our existing default *.

@zhengweiwithoutthei
Copy link

The scenario where the publisher has no policy and the embedded frame does not want to propagate permission, the allow-recursive solution does not require the frame to act (as it does not have permission), whereas the default * does require the frame to act.

I am not sure this is correct. I believe, with default as '*', permissions-policy: attribution-reporting=() is sufficient to disable the feature for all nested frames. I made an example at https://attribution-permission-policy.glitch.me/?disable

By removing '?disable' you can see all nested frames has the feature enabled without 'allow' attribute which indicates the defualt '*' is in use.

Appending the '?disable' introduces the permissions-policy: attribution-reporting=() header in the response to the top document, and it effectively disables the feature in all nested frames without the frame to act individually.

@csharrison
Copy link
Collaborator

I am not sure this is correct. I believe, with default as '*', permissions-policy: attribution-reporting=() is sufficient to disable the feature for all nested frames. I made an example at https://attribution-permission-policy.glitch.me/?disable

Yes that's true. I would consider that a case where the publisher has a policy though, right? I was describing a case where the pub does nothing.

@jfggit
Copy link

jfggit commented Jan 12, 2023

There's a kind of use-case gap with the allow-recursive solution which is somewhat unfortunate. I think we kind of hashed this out above, but to make it explicit: We have publisher, SSP, and DSP, where the publisher loads the SSP's code into their top level, the SSP creates an iframe to fetch ads, and the DSP executes within that frame. The SSP, as the creator of the iframe, has the ability to use allow-recursive to enable the feature to any children frames. However, the publisher does not have a way to do the same. Clearly they have the "permission" to, but from a technical standpoint there's no mechanism for them to specify that (other than maybe to make their own iframe to contain the SSP).

@csharrison
Copy link
Collaborator

@jfggit that's true. I wonder @clelland if permissions policy ever considered making the top level headers "automatically" set the allow bits on iframes from an ergonomics POV?

@clelland
Copy link

It originally sort-of-did that, or at least the header could be used to automatically apply those bits to child frames by origin. We changed that a few years ago, in order to make it possible to absolutely block any origin (including your own) from the header (w3c/webappsec-permissions-policy#357)

@WICG WICG deleted a comment from Voykin Jan 12, 2023
@jfggit
Copy link

jfggit commented Jan 19, 2023

To be clear, does that then preclude re-adding such a mechanism, or otherwise implementing it in a non-conflicting way? @clelland @csharrison

@clelland
Copy link

I'll speak to the same at the CG meeting, but my biggest concern here is that an allow-recursive as described essentially silently changes the default allowlist to * at a point in the frame tree. Sites wouldn't necessarily know that it has happened, or perhaps even that it could happen, if we made this a general part of permissions policy.

I think that if we were to try something like this, it would need to be a feature-specific addition (or a flag that could be set on specific features, initially just this one), and it might need to be scoped to specific origins. That is, maybe you can't set it to *, but you could specify certain origins that would be recursively allowed unless blocked.

@csharrison
Copy link
Collaborator

my biggest concern here is that an allow-recursive as described essentially silently changes the default allowlist to * at a point in the frame tree

Any thoughts on how we could make it visible, like the ideas in the original comment:

To prevent security issues from silently propagating permissions, we would need to ensure that frames understand what is happening and what their recursive policy is, e.g. via HTTP headers or JS accessors

This doesn't fully solve the problem but seems like a decent mitigation.


I think that if we were to try something like this, it would need to be a feature-specific addition (or a flag that could be set on specific features, initially just this one)

I am 100% with you on making this feature-specific (or a flag on specific features). I am not interested in changing the behavior of all other features. I might only expect some ads-specific features (e.g. Topics) that share the same use case of depending on an ecosystem of nested iframes to want this.


and it might need to be scoped to specific origins. That is, maybe you can't set it to *, but you could specify certain origins that would be recursively allowed unless blocked.

I can see the appeal of this, but I wonder how doable it would be in practice. This will be a good discuss to ask the group in today's meeting, but I can imagine this having issues if the SSP does not have full information about the final
iframe in the chain (e.g. because of recursive auctions, etc), and intermediaries are broken and don't configure themselves to propagate the permission.

@csharrison
Copy link
Collaborator

Summarizing the discussion from Jan 23

  • @jfggit and I voiced concerns about requiring listing out specific origins (per @clelland's comment here), but I suppose we don't have any conclusive evidence that a chain of delegation couldn't work in the long term.
  • @bmayd brings up a new point which is that the ability to turn off the API for children could be a footgun leading to accidents, or something a malicious party could do. There is a desire for visibility about what's going on, relevant to parallel work Usefulness of reporting in Permissions Policy w3c/webappsec-permissions-policy#386.
  • We discussed whether we could support a setting where e.g. ad frames wouldn't be able to turn off the feature for their children, but there were some counterpoints that the top level shouldn't have a monopoly on security decisions (e.g. deciding which subtrees are ad trees or not, and have the privilege of turning off the API).
  • We discussed that the likely end state is that all ad frames just always allow in a default self world, which I think is probably a fine outcome, as long as it satisfies the non-ads use cases.
  • We recognized that we probably want alignment with Topics and FLEDGE, so cc @jkarlin / @JensenPaul :)

Let me know if I missed something major. I'll try to synthesize some of these points into a path forward.

@SteveRupp
Copy link

The Permission Policy requirement for cross-domain iframe would require large scale advertiser and publisher outreach to enable the APIs in the cross-domain context.

In general for buyside Adtech, driving publisher outreach is a challenge because the direct customer relationship is with the advertiser, not the publisher. When advertisers work with publishers it is typically around ad trafficking changes, not site permissioning.

Scale can be another challenge for outreach. Buyside AdTech can easily have ad tags deployed to thousands of publishers which makes the scale of outreach to all but a top handful of publishers challenging. Multiple ad techs and measurement providers can interact with a given ad slot, which also complicates ensuring that policies are updated correctly for all parties so that consistent measurement is possible.

Furthermore, Publishers would likely no longer be able to accurately measure the impact of their media due to some advertisers not having turned this on which might limit the effectiveness of the APIs for the ecosystem.

The current proposal to enable cross domain iframe support by default for publishers and advertisers would simplify and streamline adoption of the Attribution Reporting APIs. We also believe that easy opt outs for those who don't want to participate strikes the right balance between building an effective privacy preserving APIs and giving partners the right choice of controls over the API usage.

@csharrison
Copy link
Collaborator

After all the previous discussions, I feel a default permission policy of self is not feasible for a near-term launch of the Attribution Reporting API:

  1. There are real-world deployments of ads where unknown intermediaries can be present in an iframe subtree. Any one of these can break measurement in a subtree by forgetting to place the correct allow attributes. This leads to problematic, fragile deployments. I want the API to be reliable.
  2. Some publishers maintain in-house tools for ads serving (e.g. for reservation ads or explicitly framing their ad tags). Getting these publishers to adopt the permission policy might be more difficult than in the programmatic ecosystem with a fewer # of SSPs that need to adopt.

As such, I am proposing we stick with default * for the time being, even after the Origin Trial. I still believe * is preferred over no policy at all, even if it allows a potential for accidental footguns. This is because it still allows some measure of control for privacy sensitive parties. This aligns with the SharedStorage and Topics APIs, which use default *.

That being said, I’m still interested in investigating possible improvements to the permission system (e.g. refining the recursive-allow proposal, or something entirely different), but I wouldn’t want to block shipping the API over that longer-term cross API design work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants