New issue
Advanced search Search tips
Starred by 4 users

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Windows , Chrome , Mac
Pri: 1
Type: Bug

Blocked on:
issue 804888



Sign in to add a comment

Site isolation prevents being able to click on elements within invisible iframe

Reported by dan...@breadfinance.com, Jun 3

Issue description

Chrome Version       : 67.0.3396.62 (Official Build) (64-bit)
URLs (if applicable) : https://sy.factoryoutletstore.com/cat/47766/Sealy-Full-Size-Mattresses.html as one example
Other browsers tested:
  All OK except for Chrome with site isolation
have tested this issue:
     Safari:
    Firefox:
       Edge:

What steps will reproduce the problem?
Click the links in the button at top or at the bottom of the left side that say "Pay over time with Factory Financing"

What is the expected result?
A modal overlay should appear with a financing application form

What happens instead?
Nothing

Please provide any additional information below. Attach a screenshot if
possible.
As these pages load, iframes are dynamically created and populated to create secure environments for people to apply for financing.  For some reason, in some circumstances, site isolation doesn't impact the intended behavior.  To see an example, on the same page, click on any of the "Pay Over Time: as low as X" links below the add to cart buttons, and everything works as expected.  However, for some reason, in another code path that is more or less identical, the buttons at top and left do not work.

Looking into it, it appears that while a click event is being successfully attached to elements within the iframe's DOM, the iframe itself is capturing all mouse events and preventing events from targeting any elements deeper in the hierarchy.  You can see this throughout; for instance, try to use Chrome dev tools to select an element for inspection within the iframe's DOM, and you cannot; the iframe itself grabs the focus.

This problem goes away with site isolation off.

This is a critical issue and is impacting our customers.  What is the workaround?

 
Further update - this issue exists when the iframe has a style of opacity: 0.  Everything works fine for higher values.  This problem only exists when site isolation is on.
Labels: Needs-Triage-M67
One further update - because we could not wait, we improvised and deployed a workaround by setting the iframe's opacity to 1 and its inner element's opacity to 0 to get the same appearance, and it is now behaving correctly.  So you will no longer be able to reproduce the bug at the URL provided.

But you should be able to reproduce this issue yourselves by having a click handler on an element inside an iframe served from domain B, hosted on a page from domain A, when the iframe has style of opacity: 0.  The inner element will never receive the mouse event.  I believe this is a bug in site isolation in Chrome 67, and not by design.

Comment 4 Deleted

Labels: Needs-Bisect
I tried to put together a simple repro page and could reproduce the bug reported on M67 but not on M68 and M69 with Site Isolation enabled. It will be useful to understand what CL fixed the issue. 

The repro pages is https://web.evilbit.io/iframes/outer.html and contains two frames with the same document - first is same origin, second is cross-site. Click on the frame generates a console message with the number of clicks received and changes the document to contain that string (though because of opacity 0 it is not visible).
Cc: kenrb@chromium.org creis@chromium.org
To reproduce go to: https://sy.factoryoutletstore.com/cat/47766/Sealy-Full-Size-Mattresses.html

Add "opacity: 0" to the iframe with the id #bread-promo-0-bread-iframe.

document.getElementById('bread-promo-0-bread-iframe').style = 'opacity: 0';

Using chrome 67 with chrome site isolation enabled. Click on the #bread-promo-0-bread-iframe. Which is the 'Pay Over Time With Factory Financing' button at the top.

Click events are not firing.

I can also confirm the bug does not occur in chrome 69.
Unfortunately a bisect did not find any build that works, so I wonder if this is a combination with another feature that might be enabled on Beta/Dev/Canary but not on Stable yet.

kenrb@ are you aware of what other factors can be in play here?
Cc: fsam...@chromium.org gov...@chromium.org
Components: Blink>HitTesting Internals>Services>Viz
Labels: -Pri-3 FoundIn-67 OS-Chrome OS-Linux OS-Mac OS-Windows Pri-1
Owner: kenrb@chromium.org
Status: Assigned (was: Unconfirmed)
Sounds like a possible Viz hit testing bug?  Ken (or Fady), can you take a look to see what might be going on, and what might have fixed it in official M68 and M69 builds (e.g., a field trial, perhaps)?  Thanks!
Cc: sadrul@chromium.org
+sadrul@
Ok, I've made a mistake in how I tested and fixing that I can no longer see the issue working, therefore I don't think it is fixed :(. 

On comment #7, I wonder if your M69 Chrome is just in the control group for our trial. Would you mind pasting here the variations you have listed in chrome://version?
I can still see the problem in Chrome 69.

This likely answers the question of why site isolation was breaking a lot of ad fraud sites. It seems that invisible cross-origin iframes can't currently be targeted by input events. This is a corner case that we missed when we added asynchronous hit testing.

I can repro with Nasko's test page on Canary (Chrome 69), and I wouldn't expect it to be fixed.

Workarounds should be fairly straightforward. opacity:1 would be the simplest way. It would also work to put a different cross-origin iframe underneath the invisible. More broadly, why are you creating an invisible cross-origin iframe and expecting it to capture input events?

I suspect the reason this hasn't been noticed until now is that it's not something we often see on the web (except when used for ad fraud, where it is common). We'd be interested in better understanding the motivation for it.

This would be difficult to fix before Viz hit testing is turned on. I believe the fix would be adding a hack to the compositor to emit drawquads for invisible iframes, but the work involved might not be justified for a short term fix to a rare use case.
Cc: rjkroege@chromium.org
+Rob
Do we not always fall-back to async hit-testing for oopifs? If we do, the absence of a draw-quad for the invisible iframe should not be an issue, right? chrome should still do async hit-testing, and the main-page should return the oopif as the target?
If there is no SurfaceDrawQuad for the invisible iframe, then the quad-based hit testing doesn't know there is an iframe there, and it doesn't fall back to asynchronous hit testing.
Labels: Target-68
Summary: Site isolation prevents being able to click on elements within invisible iframe (was: Site isolation prevents being able to click on elements within iframe)
I see.  So when Site Isolation is enabled, input events are not sent to opacity:0 cross-site iframes (unless there's a separate iframe underneath them).

Reporters: Can you comment more on the use case, as kenrb@ was wondering in comment 12?  What is the motivation to have a transparent cross-origin iframe that receives click events?

We're in a bit of a halfway state right now, and we need to decide which way to go.  Either this behavior should be considered a use case to support and input events should go to hidden cross-origin iframes, or it should be considered invalid and we should prevent it in all cases (including those when another iframe is underneath the hidden one).

It does sound like this technique is more commonly used for clickjacking and ad fraud, where users don't realize what they're clicking on (e.g., a hidden ad or button that causes an unwanted action).  Thus, we might want to start discussions around spec changes to make it off-limits in general, including when there's an iframe underneath.  Ken mentions that this has been considered in the past.

However, we would want to take input on legitimate use cases for this behavior in those discussions as well.

Either way, we probably want to try to restore the existing behavior in the meantime, rather than staying in the halfway state where it's broken in some cases but not others (e.g., if there's an iframe underneath).  Ken, can you look into the change to emit SurfaceDrawQuads for invisible frames, or help find an owner?

Given that the original site has a workaround and that the only other affected places we know of are malicious, it might be sufficient to get the fix into M69 and hopefully merged to M68.  M67 is a high bar at this point, but we could re-evaluate if additional legitimate use cases turn out to be affected.
Cc: abdulsyed@chromium.org

+abdulsyed@ (M68 Release TPM as FYI)
Labels: M-68
To be clear, the idea of having a separate iframe underneath the invisible iframe and its underlying content would just be a hack to trigger the correct path in our hit testing system.

Another way to work around this, which is also known to fraudsters, is to put the iframe underneath other visible content and give that content pointer-events:none. That way the click passes through the visible part and hits the iframe that is visually obscured. This achieves the same effect, and works correctly with site isolation.
Reporter here.  The use case here was a legacy thing we did out of expediency (not for clickjack fraud!).  Our interface typically presents as an iframe where we display the contents to the user (as in the "Pay Over Time $/month" links in the example URL provided).  When we added a feature where our customers could, on their sites, attach our behavior simply to any <div> with any content on their own, out of expediency we simply overlaid our existing button iframe onto the host's <div> and used opacity:0 to make it invisible.

Had this been an issue at the time we built it, I'm sure we would have taken a different approach - there's no fundamental need for us to have an invisible iframe.  But having built it the way we did, the Chrome 67 rollout broke our customers' sites as a result.  It continued to work as designed on all other browsers and earlier versions of Chrome.  It doesn't sound from this thread like this change of behavior was by design, but I could be missing something.

Regardless, we've worked around the issue for now by making the iframe opaque and its content transparent.
Labels: -Needs-Bisect -Target-68 -Needs-Triage-M67 M-69 Target-69
Comment 20: Thanks!  That's useful context.  Indeed, this wasn't an intentional change, and we'd like to get to where this case is either supported (as before) or reach agreement with other browsers that it should not be supported.  Sorry about the unexpected impact in your case when Chrome 67 rolled out, but glad to see you were able to quickly deploy a workaround.

We'll continue to watch for other sites impacted by this issue while we look into how to address it.  It sounds like the long term work on Chrome's Viz hit testing effort could resolve it, but Ken is looking to see what we should do in the meantime.

Since it sounds like the workaround may be sufficient in this case for the time being, I'm going to suggest targeting the fix at the M69 branch (current Canary/Dev) to avoid unnecessary merges, but also to give us options (e.g., merging to M68) if it turns out to affect more sites.

Comment 22 Deleted

One more note in case you go the route of disallowing this functionality in the future is that using 'filter: opacity(0%);' on the iframe and clicking on it does send the input event to the cross-site iframe in chrome 67 with cross-site isolation.
Cc: sunxd@chromium.org
+sunxd@
I've tested with v2 hit testing (--use-viz-hit-test-surface-layer) and site isolation, while setting the opacity to 0, it seems the event was handled and overlay shows up.
In addition to comment #25, you have to manually disable "Viz Hit-test Draw-quad version" in chrome://flags and add the arg mentioned in #25 to use v2 hit testing, as the presence of any other hit test data provider would disable v2.
Comments 25-26: Thanks for checking, sunxd@!  I can confirm that the bug is gone in that configuration.  Do you know the launch bug for v2 hit testing, so that we can mark this blocked on that?
Blockedon: 804888
Issue 810128 has been used as a tracking bug for the work that would cover v2, although it isn't a proper launch bug. The only launch bug I see is issue 804888, so I'll add that as blocking.

Sign in to add a comment