-
Notifications
You must be signed in to change notification settings - Fork 155
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
How should iframe navigations work? #38
Comments
If we grant X to iframe, that iframe can embed any other iframe and grant X to its descendant... IMO redirects are fair game here. If we grant X to an origin/frame and that frame redirects, then it is, in effect, delegating that (full/same) access to the redirect destination. |
I wasn't thinking about redirects specifically. Consider the case where I embed "google.com" and give it geolocation access. The user does a search in the iframe and clicks on a search result which navigates to a random website, bad.com. In this case, neither the top level page, nor the embedded page has given any indication that bad.com should be given access. We had the same principle of revoking access for permission delegation. I think the same applies here. Thoughts? |
FWIW, I think redirects are very common.. if we revoke the feature on redirects, I think that'd be a very painful experience for a lot of pages. Re, navigations: this smells like a CSP + FP policy combination.
The discussion for navigate-to is w3c/webappsec-csp#125, and rumor has it, embedded CSP implementation may be underway in Chrome. /cc @mikewest |
Hmm - I understand the concern now. I still don't feel very comfortable with this from a security standpoint though, at least in the general case of one site navigating to another, for example navigating by setting window.location or by a user clicking a link. There is no indication that the site trusts the feature to be delegated to the site being navigated to. Furthermore, the original origin is now out of the picture and is no longer an active actor in the scenario. It no longer holds any responsibility for the actions of the navigated site. It's different in that sense from the frame embedding a site and actively delegating access. I think I'd feel more comfortable if ads that needed it added in an extra iframe in their chain where all the redirects happened and they could delegate access to all origins they embed. I'd be curious of the view of some security folks too :) |
The page can already limit the things its frames can navigate to by setting
This is made worse by the fact that frames are navigable cross-origin. That is, if I have a handle to your window (via It would be unfortunate if that gave folks a trivial way of gaining permissions that had been granted to someone else. |
We decided on the syntax If that's problematic, (and it seems that it is,) then we could change the interpretation of the shorthand, to explictly mean: "enable the feature in this frame for the initial origin embedded in it". We could also change the syntax, to require developers to write something like
or even require something like the JSON used for the full policy:
If a site really wanted to allow a feature to all origins potentially embedded in the frame, then it could
to allow that. |
@clelland that's a good point :) I think the simplest thing, most secure and most common case is to delegate the feature only to the initial origin. I feel like that's good syntax to keep. We could add additional syntax to specify which origins specifically as you suggested - I think we would want to make it a bit scarier because I think the guarantees are much less obvious. Just brainstorming: would a separate attribute feature-policy="..." which allows specifying a full policy to override the header, but only for that iframe be a better approach? This would be scarier/more complicated but give full control. The enable/disable syntax would just be sugar for specifying the full policy. Is there precedent for specifying json in an attribute? |
Can we nail down the threat model we're trying to address and how and why existing methods are insufficient? I'm still dubious of the solutions we're driving towards here..
As @mikewest pointed out, if the top-level frame wants to protect itself against subframe's navigating themselves, it can use frame-src.. For sub-iframes, I believe the same frame-src via embedded enforcement applies? How or why is the above not sufficient? I'd rather layer the various mechanisms, instead of trying to reinvent the wheel multiple times.
Not sure if it's simple.. But I'm pretty confident it's a non-starter for most interesting use cases -- e.g. ads, which often bounce through a series of redirects. |
I think what we're really discussing is what the scope of an "enable" attribute should be by default, i.e. to which origins in the iframe should it apply (@clelland stated it well above :). @igrigorik it seems like your preference is that by default an enable attribute should apply to any origin that gets loaded in the iframe to which it applies. If the embedder wants to prevent this from happening they need to restrict navigations by using another mechanism, e.g. frame-src. Is that accurate? I'm not sure this is the best approach. It seems too easy to accidentally give geolocation to any origin that gets loaded in the iframe, and these origins might not be trusted by anyone. It means that in order to achieve least privilege, a developer first has to open up a big hole with "enable" and then subsequently lock it down with extra navigation restrictions. I think that people will be shooting themselves in the foot because they don't realize how broadly they are delegating access and they forget/never realize to lock it down afterward (see the examples above). That's why it seems preferable (from a security standpoint) to go the other way around: by default "enable" is scoped to the initial origin and if a developer wants it apply more broadly they can explicitly specify that.
I agree :) I think we need to find a solution that addresses this too. I'm just not sure that having enable apply to all origins that get loaded (by default) is the best approach. |
I wouldn't say it's a preference, as much as.. a coherency and layering question: if sandbox whitelist grants privilege to all origins of the frame, then FP should -- I think -- follow the same model. That way, at least we have a single and simple path for developers: if you need to constrain the granted privileges use frame-src, etc. Mixing frame-src with special enable syntax for FP, with.. (insert whatever other mechanisms we dream up later).. is unmanageable. I understand your concerns though, and I agree with them. I'm just arguing for a single mechanism to govern all this, instead of ad-hoc approaches in each mechanism. |
It's a good point that sandbox doesn't revoke access on navigations, but I think there is an important difference. Sandbox is all about locking things down, rather than giving extra privilege. It's more like the "disable" attribute than the "enable" attribute. I think it would be ok (preferable) for the "disable" attribute to apply to all origins that get loaded in the iframe, just not enable. With FP we're considering delegation of powerful features. We need to be very careful that trust has been explicitly expressed by someone before giving access. I don't think that happens when enable applies to all origins in a frame. Going back to the original example I had, I don't think this will be acceptable from a security standpoint, even with the fact that navigations can be restricted:
|
Well, there is a reason why we don't allow google.com to be iframed (x-frame-options:SAMEORIGIN).. :-) The destination can protect itself by x-frame-options, the embedder can protect itself via CSP frame-src, right? That said, what's the concrete proposal we're evaluating at this point? As I said earlier, I think we're solving this at the wrong layer, but I'm happy to be convinced otherwise. |
I don't think the reason we prevent google.com from being iframed is related to this issue though? It's easy to use other sites as an example, like bing.com that don't have x-frame-options. I don't think this isn't about the embedder or the destination protecting itself - rather the embedder being very specific about who they delegate access to. Having a default that grants access very broadly is a recipe for the embedder giving access to someone unintentionally. The options we were discussing were to have "enable" apply only to the origin in "src" by default and having a way to broaden that access if the embedder really wants to, for example by having an additional attribute which allows specifying a full policy to apply to that frame. There are lots of variations of that idea that I'm open to though. |
Discussed on VC today, the proposal is:
The former enables "full policy" syntax, which also allows the embedder to delegate permission to all origins (e.g. to deal with unknown redirects, etc). The latter (shorthand) |
The shorthand is equivalent to:
but is shorter, and hopefully less error-prone We still need to resolve what happens if both attributes are specified -- whether for the same, or for different features, and whether changing the |
Updated proposal in https://docs.google.com/document/d/1k0Ua-ZWlM_PsFCFdLMa8kaVTo32PeNZ4G7FFHqpFx4E/edit#heading=h.t3vfp0hdaogx. Anything else we need to address on this one, or can we close it and iterate in the explainer? |
Closing this -- the end result of this is that the policy applied by the parent document to its child frames can specify a list of origins, (a single origin in the limit) or allow all origins loaded in the frame to use the feature ("*"). The iframe For compatibility, the |
What should we do in the case where an iframe navigates itself to an origin other than the one it is initialized to?
One case to consider here is, the embedder says enable="geolocation" for an iframe initialized to "good-site.com" but then the iframe is navigated to "bad-site.com". We don't want geolocation to be enabled.
A potential solution is to ignore enable attributes after a cross-origin navigation has occurred, unless the enable attribute is modified and then the iframe reloaded.
We also need to take care to apply the parent frames header policy correctly when an iframe is navigated to a new origin.
@clelland @mikewest @igrigorik @ojanvafai
The text was updated successfully, but these errors were encountered: