w3c / ServiceWorker

Service Workers
https://w3c.github.io/ServiceWorker/
Other
3.63k stars 313 forks source link

serviceworker for iframes with srcdoc #765

Open ConradIrwin opened 9 years ago

ConradIrwin commented 9 years ago

As I understand it <iframe seamless="seamless" sandbox="allow-same-origin" srcdoc="<img src='/example.png'/>"/> should load /example.png as if it was on the containing page.

To this end, I feel like the navigation should go via the parent page's service worker's fetch event.

Unfortunately this doesn't work in either Chrome or Firefox because the srcDoc has no document.URI, you can see the current behaviour here: https://cdn.rawgit.com/ConradIrwin/2194f982494ba943a4c0/raw/ec0a6d3ebe69e2953e10d049005065de85588fa0/iframe.html

I'm trying to understand if this is a deliberate feature "iframes with srcdoc should not inherit the parent service-worker under any circumstance", or an edge-case that wasn't considered.

My use-case is loading emails into an iframe, I'd like to be able to fetch resources in the emails using the service worker so that I can load attachments as inline images.

jakearchibald commented 9 years ago

F2F:

srcdoc iframes with allow-same-origin should link up to the parent's service worker. We need to double check about:blank.

It's likely this change would happen in HTML, and we need to consider other inherited state outside of serviceworker.

+@mikewest

jungkees commented 8 years ago

Filed an issue: https://github.com/whatwg/html/issues/321 and made a PR: https://github.com/whatwg/html/pull/322.

wanderview commented 8 years ago

Gecko bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1264179

jakearchibald commented 8 years ago

Pre F2F notes: doesn't look like there's anything to discuss here

jungkees commented 8 years ago

F2F: The behavior here has been decided: an iframe with srcdoc will get a controller from its parent. The thing left here is to sort out the spec text with other changes for client-creating and hooking into html: https://github.com/slightlyoff/ServiceWorker/issues/870.

jungkees commented 7 years ago

Currently working on this. Process the iframe attributes algorithm is where it seems the logic should be added (or at least the parts related with this algorithm.)

Note: I strongly feel both about:blank (no matter whether it goes through fetch or not) and about:srcdoc should NOT have a controller. They are NOT able to match any registration, so should be considered in non-controlled state. (The active service worker of those documents' environment is null by default.) So, going back to the OP issue, only when sandbox="allow-same-origin" comes together with srcdoc="/* source */", the iframe should inherit its parent's active service worker, if one exists.

wanderview commented 7 years ago

Note: I strongly feel both about:blank (no matter whether it goes through fetch or not) and about:srcdoc should NOT have a controller. They are NOT able to match any registration, so should be considered in non-controlled state. (The active service worker of those documents' environment is null by default.) So, going back to the OP issue, only when sandbox="allow-same-origin" comes together with srcdoc="/* source */", the iframe should inherit its parent's active service worker, if one exists.

Since about:blank iframes inherit the origin from the parent, I don't see why they shouldn't inherit the controller as well. Without this how can a page programmatically build an iframe DOM in an offline state? Elements added to the child frame wouldn't be intercepted.

mkruisselbrink commented 7 years ago

I'm kind of on the edge about about:blank inheriting a controller. It does seem somewhat weird if about:blank iframes wouldn't inherit the controller. But it also does seem a bit arbitrary, as in where do we draw the line. Should all same origin iframes that have a URL that can't possibly be in scope of a service worker inherit the controller from their parent (for example blob URLs)? But maybe that inconsistency isn't too bad, and about:blank iframes (and windows?) are probably used a lot more than blob URLs anyway.

asutherland commented 7 years ago

Taking a step back to the use-case (as a reformed HTML/JS email app developer myself), I think the scenario is that the page is embedding third-party content (emails, rich HTML "chat" messages, tweets, maybe ads when the ad-blocker wars get worse) and Service Workers provide a simple abstraction to control remote network access in a powerful way that the sandbox attribute and CSP do not and cannot. The alternative to using Service Workers in these cases is to use data documents and understand 100% of the semantics of the HTML nodes and CSS rules applied to them in order to re-write or block the remote network accesses depending on the goals[1].

I think it's worth asking whether it's more appropriate to create a logically distinct affordance like "sandboxfetch" to explicitly recognize this use-case and enable good hygiene rather than have it depend on a carefully defined spec grey-zone. There's been interest in ideas like this before, see the public-webappsec Jan 2016 discussion on "In-browser sanitization vs. a “Safe Node” in the DOM" and Feb 2016 follow-up thread.

The primary benefit from such an approach would be to enable clever use of ServiceWorkers with embedded third-party content without enabling a class of XSS "gotcha!" where malicious sandboxed content is able to leverage naive ServiceWorker implementations. With explicit "sandboxfetch", the ServiceWorker author has to opt-in to handling the logic rather than being surprised.

1: For the example of an email app, goals would be as follows, with https://github.com/cure53/DOMPurify a common implementation choice:

jungkees commented 7 years ago

To clarify the spec point of view first,

Since about:blank iframes inherit the origin from the parent, I don't see why they shouldn't inherit the controller as well. Without this how can a page programmatically build an iframe DOM in an offline state? Elements added to the child frame wouldn't be intercepted.

You're right. I was focusing only on the document's URL and registration matching perspective and missed the point that they inherit the origin. (I confirmed it by testing with the browsers a bit but am still looking for the specific steps in the specs that inherit the origin though. The part in HTML spec is https://html.spec.whatwg.org/#creating-a-new-browsing-context step 8.)

That said, the behavior should be somewhat opposite to what I said in my note above. So, iframes having their src set to non-http(s) URLs (i.e. including about:, blob:, etc.) or their srcdoc is set will inherit the parent's controller. But navigation matching still wins, so when a navigation goes through HTTP fetch the matched registration's active worker replaces the inherited active service worker. When sandbox attribute is set without allow-same-origin token, it won't get a controller (set to null, precisely).

But it also does seem a bit arbitrary, as in where do we draw the line. Should all same origin iframes that have a URL that can't possibly be in scope of a service worker inherit the controller from their parent (for example blob URLs)?

I think so. The way how they're dealt with is the same as the about:blank case (not reaching http fetch to get the resources), and the fact that those iframes inherit the origin seems like a basic premise that they should get the parent's controller.

jungkees commented 7 years ago

@asutherland,

I think the scenario is that the page is embedding third-party content

I think if the main resource to the iframe is a cross-origin resource in the first place, it should go with its own registration matching. So, I presume the use-case in the OP is loading a resource as a same origin iframe srcdoc document and expecting its subresources will be fetched through the inherited controller (and foreign fetch SWs if they're implemented and avaiable.)

I think it's worth asking whether it's more appropriate to create a logically distinct affordance like "sandboxfetch" to explicitly recognize this use-case and enable good hygiene rather than have it depend on a carefully defined spec grey-zone.

Assuming the use-cases you pointed out here are iframes loading third-party main resource (note that object tag falls back to network early), they should get their own controller by matching a registration rather than inheriting one. In this regard, I don't think this case poses any addtional threats. Am I misunderstanding any of your concerns here?

yoavweiss commented 6 years ago

Was there any progress made on this issue?

wanderview commented 6 years ago

FWIW firefox now makes srcdoc frames inherit the parent's service worker controller. We have a WPT as well:

https://github.com/w3c/web-platform-tests/blob/a3a5824500bdf2515114c6653253a9d8d172d37a/service-workers/service-worker/about-blank-replacement.https.html#L167

isubasinghe commented 5 years ago

Hey guys, I had a problem which I believe is caused by this issue, it would be greatly appreciated if I could get some input on this bug I'm facing.

I use a 3rd party plugin which uses an iframe to render content, inside this iframe a srcdoc defines html including some assets to load (js libraries). In chrome 73, offline functionality is broken because the js libraries loaded in this iframe are not cached by the service worker ( I believe this to be the case anyway as it works fine on the latest chromium and firefox builds).

Are there any hacks to make this work in older versions of browsers?

Thanks 😄 !!!

jungkees commented 5 years ago

Move this to the next milestone with https://github.com/w3c/ServiceWorker/commit/2183f5e1309347acd3d8c0d5401639c6020b573c. We'll work on the normative definition of the active service worker determination in HTML Standard and Service Worker Nightly.

jungkees commented 5 years ago

@isubasinghe,

In chrome 73, offline functionality is broken because the js libraries loaded in this iframe are not cached by the service worker ( I believe this to be the case anyway as it works fine on the latest chromium and firefox builds).

Do you mean the JS files loaded in the srcdoc iframe were not captured by the service worker even though the parent frame has a controlling service worker? And it happen only on or before Chrome 73? If so, this seems like a bug that has been already addressed in Chromium. The expected behavior is the parent frame's service worker serves loading the JS library files in the iframe srcdoc document.

/cc @mattto @SteveBeckerMSFT

isubasinghe commented 5 years ago

@jungkees

Do you mean the JS files loaded in the srcdoc iframe were not captured by the service worker even though the parent frame has a controlling service worker?

Yes, this is what I meant, I was expecting the offline functionality to work regardless of it being inside an iframe.

And it happen only on or before Chrome 73?

I have only tested on chrome 73, latest chromium and latest firefox builds. It works on latest Chromium and Firefox but not Chrome 73. Happy to test it in other versions if it would help you guys out.

Unfortunately, I'm expecting some users to be using older versions of chrome, so I was hoping for a workaround.

I had some ideas to figure out a hack around this bug but they did not yield any useful results.

zkrige commented 5 years ago

I'm seeing same problem in chrome75. Service workers are not working for iframe with no src attribute

kevodwyer commented 5 years ago

Much like the email client scenario outlined by @asutherland we have a web app that uses the combination of a writeable stream and service worker request interception to be able to download chunks of encrypted data, unencrypt client side and feed a html5 video/audio element with media (not disimiliar to streamsaver.js). It is trivial to extend to arbitrary supplied static html/css/js resources and have them ultimately rendered in a sandboxed iframe.

The POC currently only works when the sandbox element is set to allow-same-origin in order for the request interception to be available. Our problem is as outlined in the html5rocks article on sandboxed-iframes [1] "If a page on https://example.com/ frames another page on the same origin with a sandbox that includes both the allow-same-origin and allow-scripts flags, then the framed page can reach up into the parent, and remove the sandbox attribute entirely." Not the sandbox guarantees we are looking for... I am seeking comment on whether this use-case has been considered and is so, an idea on the roadmap to realise a iframe sandbox where resource requests can be intercepted without the allow-same-origin restriction.

[1] - https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/

Kle0s commented 2 years ago

Chrome 104, seems like iframes with srcdoc / src="about:blank" / no src set, still do not inherit the parent SW :/

zefhemel commented 1 year ago

Current state seems to be that both Safari (tested 17.0) and Firefox (tested 118) have SWs enabled for iframes with srcdoc, just Chrome seems to be the hold out.