Closed jakearchibald closed 6 years ago
Additionally, imagine https://example.com
<a href="http://example.com/worker" target="_blank">Click me</a>
If the link above is clicked, http://example.com
now has a WindowProxy
reference to https://example.com
, but https://example.com
remains a secure context unless the state of a context's security is mutable.
As @mikewest says, .opener
is a misfeature. We could look at how much of the web would break if it were disabled when crossing schemes.
It'd be great to see numbers for "window.opener used from an HTTPS page to an HTTP page" - could we deprecate in this case?
Arg, sorry I missed this when you filed it. Thanks for the ping.
So. Heresy or not, I'm also not thrilled with the opener
restrictions, but I'm not sure that throwing them out completely is the right thing to do. I think I agree that in some cases it ends up being more confusing than helpful to taint a popup based on the way it was opened.
The general idea behind the opener restriction is to close down communication channels between secure origins and non-secure origins in order to prevent feature use in one context from leaking into another. As you note (and as described in https://w3c.github.io/webappsec-secure-contexts/#isolation), a number of communication side-channels exist for same-origin content that we haven't addressed via this restriction. Those side channels are hampered by the fact that no direct DOM access exists between the contexts, but they exist as long as we don't use the context's "secure" status to influence the origin (which I'm very reluctant to consider).
That said, the same side- and direct-channels exist for <iframe>
elements. You've suggested that you're ok with those restrictions because you recognize the risk, and further that <iframe>
is invisible and doesn't require a user gesture. I'm not sure that either of those limitations actually makes a significant difference. Getting a click to work with is trivial, and visibility only matters insofar as users would consider it odd that a window was opened. I have great faith in the ability of folks who want to work around the restrictions we're putting in place to build reasonable-feeling UI that looks like it's doing one thing, while actually exfiltrating data. More involved, yes, impossible, hardly.
Still, I'm totally sympathetic to the notion that we shouldn't punish innocent bystander sites to which a user legitimately wants to navigate. Since direct DOM access worries me much more than side-channel access, perhaps we could take the opener context's origin and content into consideration more than we do today. A pretty ugly strawman would be something like "If there's a non-secure view onto the openee's origin (or an origin which has opted into same-originness via document.domain
) in the opener's frame tree, the openee is non-secure. Otherwise evaluate it as a standalone."? I'm not sure that actually helps though, and it's even more complex and confusing than the current setup.
I'd suggest that we can pursue a three-pronged approach here:
opener
implies, which we're poking at in https://github.com/w3c/webappsec/issues/517 and https://github.com/w3c/webappsec/issues/139.opener
. I think that turning it off when transitioning schemes is appealing, but I know that a number of federated identity providers poke window.opener
in order to complete a sign-in process (as an example, all of the federated options on https://discourse.wicg.io/ rely on popups). I'm reluctant to break those for non-secure origins; I'm all for getting folks over to HTTPS, but unilaterally breaking folks' authentication mechanisms seems like quite a stick to wield.(/cc @annevk @bifurcation @hillbrad @jwatt)
1, in particular https://github.com/w3c/webappsec/issues/517 seems good (basically a signal that you want to become a new top-level browsing context rather than auxiliary, also useful if you want independent process benefits and such).
@bifurcation can be pinged through @rlbmoz.
@annevk: Yeah. A stub of that is in CSP3: https://w3c.github.io/webappsec-csp/#directive-disown-opener
I tend to agree with the ordered approach above. The more often a window can be legitimately disowned (via cross-origin navigation, or one of the opt-in options mentioned) the better, and allows for more opportunities for strong isolation in the UA (e.g., process isolation hinted at by Anne above). If these options help to re-set the "inherited" (in)secure context flag for that new window, then, that's just further incentive for site authors to apply it.
So, I don't have issue with the way the secure context flag is extended to opener windows today.
The difference between a window & an iframe is the origin that's displayed in the URL bar. It seems fine to limit iframes because the user can be unaware that the framed origin is executing code.
In regards to postmessaging, could this have been tackled as part of MIX? As in, signal a drop in security if a mixed communication happens, and allow CSP to prevent mixed communication?
https://github.com/w3c/webappsec/issues/517 will solve this for geolocation & such, but it won't solve it for service worker. We need to know if the site's SW can handle the navigation fetch, and at that point we don't know if the site is going to drop opener
.
We may drop opener
automatically for SW-controlled scopes, although I've been reluctant to introduce changes in page behaviour resulting from an empty service worker. It could be opt-in on the activate event.
I think that turning it off when transitioning schemes is appealing, but I know that a number of federated identity providers poke window.opener in order to complete a sign-in process
Do they generally use window.open
or target="_blank"
too. Might be easier to deprecate opener
on the latter when it's cross-scheme.
w3c/webappsec#517 will solve this for geolocation & such, but it won't solve it for service worker.
Origin policy?
We may drop opener automatically for SW-controlled scopes
I would be pretty happy with this resolution.
An origin policy would work here also. But I think we'll auto-disown opener if opener is a non-secure context. Happy for this to close if you are.
Sure. I'll leave the bit as "at risk" in the spec just in case we can come up with something better, but happy to close this for the moment.
Actually, let's leave this open, just for visibility.
This is causing us angst. We've been using the "is a secure context" state to warn about entering passwords on insecure pages. As a result we have confused users wondering why some of their https:// pages are warning them that submitting their password is insecure. It looks secure when they look at the url bar. Very hard to convince them that "the page might pass information insecurely via its opener" makes the page insecure. The site might be storing passwords in plain text in a world-readable file once they are securely transmitted.
Of course we could decide passwords are a special case and determine secureness differently, but if we're having trouble explaining this insecure-secure-site case to users maybe developers aren't going to get it either. If anything I'd rather just nullify opener by default if we think this is a significant case we need to stop, and make sites specify explicit rel=insecureopener to get it back (and then treat the spawned context as insecure).
@dveditz: We don't tie mixed content checks to the context being "secure", only to it being delivered over a secure transport. The password check you're talking about in Firefox seems much more similar to a mixed content check than to a "should this API be available at all" check. shrug
For the record, as of Firefox 52 we added a privileged-code-only isSecureContextIfOpenerIgnored
property to compliment isSecureContext
, and the code that checks for passwords before allowing form submission uses the former. Offhand I'm not even sure why we care to check the security of anything other than the page containing the form to be honest, but I guess the more we can get away with locking things down and pushing the Web to HTTPS the better.
As it is now I think everything in Gecko should use isSecureContextIfOpenerIgnored
instead of isSecureContext
for the reasons explained before that there is currently nothing web developers can do to avoid an insecure opener from third-party sites in browsers. We just used isSecureContextIfOpenerIgnored
for geolocation in bug 1072859 too since we noticed that's basically what Chrome and Safari did. From what I could tell Chrome doesn't implement the at-risk opener part of the spec in their secure context method. It seems like we need to remove the opener check from the spec due to it breaking websites until we have an deployed solution (e.g. the CSP ones) in browsers allowing authors to prevent the issue.
I screwed this up in Chrome, sorry for both the angst and the churn. I've dropped the section from the spec, which brings it into line with everyone's implementations. My apologies. :(
As @jonathanKingston pointed out and also illustrated by the comment from @jwatt above, Firefox does actually implement this. We have https://bugzilla.mozilla.org/show_bug.cgi?id=1410364 to align with the changed standard. It would be good if there were tests.
We have tests; @jwatt added them when we implemented in Firefox. See http://w3c-test.org/secure-contexts/
It looks like @mikewest already updated those tests in https://github.com/w3c/web-platform-tests/commit/dd83f891b80aa9b05e5fe35d1680e53c6a435b07
Ok, I know this is going to sound like heresy, but I'm thinking a window opened by a non-secure context via
window.open
or<a target="_blank">
should still be considered a secure context.I agree that an HTTPS iframe embedded in an HTTP page should not be considered secure, since that gives you an invisible and automatic way of creating a channel between the two, but
window.open
and<a target="_blank">
are visible, and both require a user interaction.Imagine
http://example.com
contains:The iframe is non-secure, but the opened tab is secure. The secure opened tab can perform secure actions, and send it to the non-secure iframe via any origin storage,
BroadcastChannel
, or in a hacky waySharedWorker
(since its security is decided by the document which creates it).If we drop the parts of the spec that take
opener
into account when deciding if the context is secure users get a more consistent experience when following links, as their seemingly top-level contexts are consistently able to access powerful features.The alternative, to combat the above, is to add
isSecureContext
to the origin identifier. Meaning otherwise secure contexts opened viatarget="_blank"
are a different origin to contexts opened to the same URL viatarget="_blank" rel="noopener"
. But that exacerbates the weird user experience.