Referrer-Policy is not respected inside iframes whose document URL was set by document.open
Categories
(Core :: DOM: Security, defect, P3)
Tracking
()
People
(Reporter: fastest963, Unassigned)
References
(Depends on 1 open bug, Blocks 1 open bug)
Details
(Whiteboard: [domsecurity-backlog1])
Attachments
(1 file, 1 obsolete file)
3.46 MB,
text/plain
|
Details |
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3278.0 Safari/537.36 Steps to reproduce: Visited https://getadmiral.com/a/reset-password/1 which sends a Referrer-Policy of "strict-origin". Actual results: Requests that originate from an iframe (with no location, see #intercom-frame) send the full referrer "https://getadmiral.com/a/reset-password/1". The following requests sent the full referrer: https://js.intercomcdn.com/frame.5e98cbe5.js https://js.intercomcdn.com/fonts/proximanova-regular.a7942249.woff https://nexus-websocket-a.intercom.io/client-test Expected results: I expected these calls to respect the Referrer-Policy and only send "https://getadmiral.com".
Updated•7 years ago
|
Comment 1•7 years ago
|
||
It appears the referrer policy is not inherited well in the case nested context browsing. See also bug 1265961, probably we may close it as duplicated
Comment 2•7 years ago
|
||
> Requests that originate from an iframe (with no location, see #intercom-frame) I don't see an iframe with that id on https://getadmiral.com/a/reset-password/1 (or indeed any iframe at all: document.querySelectorAll("iframe") returns an empty list). What am I missing?
Reporter | ||
Comment 3•7 years ago
|
||
I just tried again and see 5 iframes using querySelectorAll. Make sure you don't have an ad blocker or script blocker that might be blocking Intercom from loading. You should see the little intercom bubble in the bottom right of the page.
Comment 4•7 years ago
|
||
(In reply to James Hartig from comment #0 > https://js.intercomcdn.com/fonts/proximanova-regular.a7942249.woff I guess this one also should be related to CSS. We are still not supporting referrer policy to the resource referenced from stylesheet.
Comment 5•7 years ago
|
||
Ah, I have to disable tracking protection (which means that whatever things are loading there do not respect the Do Not Track header...) The <iframe id="intercom-frame"> is NOT a srcdoc iframe, so bug 1265961 is not really relevant here. It's not quite clear to me yet how that iframe gets set up (e.g. it doesn't have about:blank as a URL... maybe it's via document.open/document.write?). In any case, I see nothing in https://html.spec.whatwg.org/#script-settings-for-window-objects:concept-settings-object-referrer-policy that would "inherit" the parent document referrer policy here. Nor do I see anything else in the HTML spec that would set that up. Can you explain why you expect the parent's referrer policy to apply to the child here?
Reporter | ||
Comment 6•7 years ago
|
||
I expected the parent's referrer policy to apply because there are requests from within that iframe that have a referrer of the parent. If it isn't inherited there's no way for the parent to control the referrer policy and we will have no way (except by not using Intercom) to prevent leaking the referrer. Additionally, Chrome seems to handle this and not send the referrer, but I'm not sure if they're in the wrong here or Firefox is. The iframe is being created via the following code: w = function() { var n = document.createElement("script"); return n.type = "text/javascript", n.charset = "utf-8", n.src = o, n } var n = document.createElement("iframe"); n.id = "intercom-frame", n.style.display = "none", document.body.appendChild(n), n.contentWindow.document.open("text/html", "replace"), n.contentWindow.document.write("\n <!doctype html>\n <head></head>\n <body>\n </body>\n </html>"), n.contentWindow.document.close(); var t = w(); return n.contentWindow.document.head.appendChild(t)
Comment 7•7 years ago
|
||
Mike, Anne, what's the story with the spec here?
Comment 8•7 years ago
|
||
Oh, and I agree that referrer policy and referrer should be coming from the same place, generally. And in Firefox they do, as far as that goes. What's basically going on here is that document.open() gives the document in the iframe the same URL as the document where the script that calls open() started running. See https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document-open-steps step 23. But this does NOT copy over the referrer policy involved. So when the script load happens in the subframe, it uses the URL of the script's document as its referrer, and uses that same document's referrer policy. And the referrer policy is empty. So Firefox is certainly following what the spec says here. Chrome is not, apparently. In terms of working around this behavior (which may be a spec bug), not calling document.open() would help. So maybe something like this: var n = document.createElement("iframe"); n.id = "intercom-frame"; n.style.display = "none"; document.body.appendChild(n); var t = w(); n.onload = function() { n.contentWindow.document.head.appendChild(t); } Assuming the async append is ok.
Comment 9•7 years ago
|
||
Actually, that might not work either, because of some referrer-inheritance stuff about:blank does. :( In fact, in that situation Chrome will also send a referrer based on the about:blank document's parent's URL, but not use the parent's referrer policy, as far as I can tell.
Updated•7 years ago
|
Comment 10•7 years ago
|
||
I filed bug 1424907 on the about:blank behavior.
Comment 11•7 years ago
|
||
I don't understand how this is different from the about:blank case. When the <iframe> is created it's document is about:blank. Invoking document.open() neither changes the document's referrer nor its referrer policy per the specification. I guess you're saying it should maybe change both?
Comment 12•7 years ago
|
||
The "document's referrer" in the sense of https://html.spec.whatwg.org/#the-document's-referrer is not relevant here. That's the referrer the document was loaded with. What's relevant is what referrer is used for loads the document does. So let's look specifically at <script src> loads. We start at https://html.spec.whatwg.org/#fetch-a-classic-script. This creates a request and sets its client to "settings object" (which is the settings object of the document). It doesn't set referrer explicitly, so https://fetch.spec.whatwg.org/#concept-request-referrer is at its default value of "client". Then we land in https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer and that ends up using the settings object's "creation URL" (per step 3, "client" branch, substep 2). That would be https://html.spec.whatwg.org/#concept-environment-creation-url (the referrer policy spec links to the W3C fork of the same). OK, so what's that in the document.open case? In the document.open case, https://html.spec.whatwg.org/#document-open-steps creates the settings object in step 17. Looks like that snapshots the then-current document URL as the "creation url". Then in step 23 the document url gets changed. That seems broken to me; I just filed <https://github.com/whatwg/html/issues/3286>. In Firefox those two steps come in the opposite order, so the new settings gets the entry settings URL. And that will get used as the referrer. Even in the (buggy) current spec steps, if you call open() twice you now have a settings object that picked up a creation URL from some entry settings but the document did _not_ pick up the referrer policy from the same place, because as you note nothing in `document.open` changes referrer policy.
Updated•7 years ago
|
Comment 13•7 years ago
|
||
Oh, I bet I know why Chrome has different behavior here. It's because they don't create a new settings object on document.open, so for them this is in fact the about:blank case.
Comment 14•6 years ago
|
||
I don't think this ends up using the creation URL. That's only used when the global object is not a Window object. When you have <script> the global object will always be a Window object.
Comment 15•6 years ago
|
||
> That's only used when the global object is not a Window object. Ah, I misread https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer step 4 to only apply to the srcdoc case. OK, so this should not be affected by https://github.com/whatwg/html/issues/3286 per se. But we do still have the possible issue that document.open inherits a url from the entry document but not a referrer policy from that same document....
Comment 16•6 years ago
|
||
Regardless of what the specs say or don't say, do we agree that the reporter's expectation are reasonable and that's the behavior we want to get to?
Comment 17•6 years ago
|
||
I believe the parts of document.open() that copy document urls should also copy referrer policies, yes.
Comment 18•6 years ago
|
||
Having thought about this some more I think the question is whether we should treat document.open() as a first-class citizen or a legacy wart. There is a ton of state we store on documents and it keeps increasing over time. We tend to forget to put it on about:blank and we tend to forget about document.open(). I think about:blank we can solve eventually as it actually creates a document so there is a common code path although in specifications and in code it may not yet appear that way. document.open() however is much less clear and other browsers seem basically content with treating it as a wart, that modifies some bits of a Document object to the extent needed for web compatibility (and leave aside other bits, clearing event listeners, and creating a new global and such). I'm personally in the wart camp as the other browsers are not willing to entertain our architecture around document.open() and this will eventually result in compatibility issues (likely for us). (Note also that the problem in OP would be solved by fixing about:blank inheritance.)
Comment 19•6 years ago
|
||
> (Note also that the problem in OP would be solved by fixing about:blank inheritance.)
In that specific testcase, yes. But if the document that the about:blank lived in differed from the entry document for the open() call, then it wouldn't be: the referrer policy would come from one place, but the referrer URL from another.
Comment 20•6 years ago
|
||
I think the reporter is right and comment 0 the expected behavior. Once we have fixed the CSS bits for referrer policy (Bug 1330487), we will return to this bug and get the spec issues resolved. I'll put this in the backlog for now.
Comment 21•6 years ago
|
||
I am having a Referrer Policy issue in an iframe loaded in a web extension’s background page where the page that is loaded still retains the default Referrer Policy value of `no-referrer-when-downgrade` despite having set the `referrerpolicy` attribute on the iframe to `no-referrer`. Is this related to this bug? I don’t use `document.open()` explicitly. Here is how I append the iframe to the background page: const iframe = document.createElement('iframe'); iframe.src = product.url; // an http(s): url iframe.id = product.id; iframe.width = 1680; iframe.height = 950; iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms'); iframe.setAttribute('referrerpolicy', 'no-referrer'); document.body.appendChild(iframe);
Comment 22•6 years ago
|
||
> despite having set the `referrerpolicy` attribute on the iframe to `no-referrer`. That, per spec, affects the referrer policy for the load of the iframe's src, but not the referrer policy of the document that ends up inside the iframe. > Is this related to this bug? No.
Comment 23•5 years ago
|
||
Christoph, what's the spec status of this at this point? Bug 1330487 is long-since fixed....
Comment 24•5 years ago
|
||
(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #23)
Christoph, what's the spec status of this at this point? Bug 1330487 is long-since fixed....
Right, in fact Thomas is working on Bug 1534681 which will fix the problem here as well. I just chatted with him and he verified that is the case. I'll add Bug 1534681 as a blocker to this one and then we can use this bug to actually land a wpt test.
Comment 25•5 years ago
|
||
(In reply to Christoph Kerschbaumer [:ckerschb] from comment #24)
(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #23)
Christoph, what's the spec status of this at this point? Bug 1330487 is long-since fixed....
Right, in fact Thomas is working on Bug 1534681 which will fix the problem here as well. I just chatted with him and he verified that is the case. I'll add Bug 1534681 as a blocker to this one and then we can use this bug to actually land a wpt test.
Sorry, I was wrong, I had to change document.open and pass callerDoc's referrer policy to current doc.
Chrome did that way and added a wpt about that, but it appears we don't have any spec says that.
So I think we should figure out what we have to do with document.open spec here. Bug 1534681 will only handle inheritance in srcdoc and blob iframe, unset dependency.
Comment 26•5 years ago
•
|
||
:annek, what do you think? Is it worth to add something points out referrer policy passing in document.open() spec (we had a wpt test but works for Chrome only) ?
Comment 27•5 years ago
|
||
Thomas, I would prefer matching https://html.spec.whatwg.org/#document-open-steps and leaving the referrer policy as-is when document.open() is invoked. Changing the WPT test and filing a bug against Chrome seems preferable here.
Dominic, do you know why Chrome modifies the referrer policy when document.open() is invoked to that of whoever called it?
Comment 28•5 years ago
|
||
The argument that makes the most sense to me here is that the URL that will be sent as referrer comes from the entry document, so the referrer policy should too. Otherwise any use of document.open() ends up risking leaking more referrer information than the document the URL comes from wanted to leak.
Comment 29•5 years ago
|
||
If that is a concern, we'll forever have to adjust document.open() to take into account new state might have to be copied over. (I guess we'll have to design some kind of abstraction to ensure this is hard not to do.)
Comment 30•5 years ago
|
||
I'm not sure specifically why we carry over the referrer policy. I imagine bz's comment may be the reason, I can ask jochen@ or someone if we're still interested in removing that from Chrome and fixing the WPT. May not be too tough of a sell, as it seems that's the only test that we currently have relying on that behavior 1. Do you still prefer that Anne?
Comment 31•5 years ago
•
|
||
I think copying state might be okay, but I'd like the answer to be more complete here. E.g., what about cookie URL (not specified yet) or CSP list?
See also bug 1534681 comment 7.
Comment 32•4 years ago
|
||
I'm afraid I still encounter this behavior which can in some situations be a serious security issue. I'd offer to help but am lacking the skills - sorry and thank you for your work.
Comment 33•3 years ago
|
||
Folks, I hate to reply to such an old thread, but I can confirm that this is still happening in Firefox (not Chrome) and is causing password reset token leaks to Intercom.
Comment 34•3 years ago
|
||
Same for me. Is there a workaround to avoid such behavior except not using services that use the technique with iframes and scripts inside them?
Reporter | ||
Comment 35•3 years ago
|
||
It looks like document.open() was clarified and https://github.com/whatwg/html/issues/3286 was closed. Does that resolve Anne's concerns about other things to copy over from the document?
Reporter | ||
Updated•3 years ago
|
Comment 36•3 years ago
|
||
I suspect this is essentially a duplicate of bug 1610450 at this point (we don't inherit into initial about:blank), but let's depend on it for now. And yeah, document.open()
just resets some state now (and does not affect referrer or referrer policy).
Updated•2 years ago
|
Comment hidden (spam) |
Updated•2 months ago
|
Description
•