Skip to content
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

serviceworker for iframes with srcdoc #765

Open
ConradIrwin opened this issue Oct 21, 2015 · 19 comments · May be fixed by whatwg/html#3725
Open

serviceworker for iframes with srcdoc #765

ConradIrwin opened this issue Oct 21, 2015 · 19 comments · May be fixed by whatwg/html#3725
Labels
Milestone

Comments

@ConradIrwin
Copy link

@ConradIrwin ConradIrwin commented Oct 21, 2015

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.

@annevk annevk added this to the Version 1 milestone Oct 27, 2015
@annevk annevk added this to the Version 1 milestone Oct 27, 2015
@jakearchibald
Copy link
Contributor

@jakearchibald jakearchibald commented Oct 27, 2015

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
Copy link
Collaborator

@jungkees jungkees commented Nov 9, 2015

Filed an issue: whatwg/html#321 and made a PR: whatwg/html#322.

@wanderview
Copy link
Member

@wanderview wanderview commented Apr 13, 2016

@jakearchibald
Copy link
Contributor

@jakearchibald jakearchibald commented Jul 27, 2016

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

@jungkees
Copy link
Collaborator

@jungkees jungkees commented Jul 28, 2016

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: #870.

@jungkees
Copy link
Collaborator

@jungkees jungkees commented Nov 16, 2016

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
Copy link
Member

@wanderview wanderview commented Nov 16, 2016

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
Copy link
Collaborator

@mkruisselbrink mkruisselbrink commented Nov 16, 2016

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
Copy link

@asutherland asutherland commented Nov 16, 2016

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:

  • Display embedded attachments (via re-written "cid:" URI scheme or implicitly embedded via attachment type which had a synthetic HTML element injected).
  • Privacy: not loading remote resources like 1-pixel webbugs without explicit user approval.
  • Offline: display pre-cached or previously loaded external resources from local storage.

@jungkees
Copy link
Collaborator

@jungkees jungkees commented Nov 17, 2016

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
Copy link
Collaborator

@jungkees jungkees commented Nov 17, 2016

@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?

jungkees added a commit to jungkees/html that referenced this issue Nov 23, 2016
This adds steps to make clients that have creator browsing contexts to
inherit the active service worker from their creators. While they have
an initial inherited active service worker, if one exists, navigation
matching still always wins. So, if the navigation goes through HTTP
fetch, the inherited active service worker is replaced by the matched
result. Also, if an iframe has a sandbox attribute set without
allow-same-origin token, the inherited active service worker is set to
null.

Related issue: w3c/ServiceWorker#765.
jungkees added a commit to jungkees/html that referenced this issue Dec 9, 2016
This adds steps to make clients that have creator browsing contexts to
inherit the active service worker from their creators. While they have
an initial inherited active service worker, if one exists, navigation
matching still always wins. So, if the navigation goes through HTTP
fetch, the inherited active service worker is replaced by the matched
result. Also, if an iframe has a sandbox attribute set without
allow-same-origin token, the inherited active service worker is set to
null.

Related issue: w3c/ServiceWorker#765.
jungkees added a commit to jungkees/html that referenced this issue Jan 24, 2017
This adds steps to make clients that have creator browsing contexts to
inherit the active service worker from their creators. While they have
an initial inherited active service worker, if one exists, navigation
matching still always wins. So, if the navigation goes through HTTP
fetch, the inherited active service worker is replaced by the matched
result. Also, if an iframe has a sandbox attribute set without
allow-same-origin token, the inherited active service worker is set to
null.

Related issue: w3c/ServiceWorker#765.
jungkees added a commit to jungkees/html that referenced this issue Jul 4, 2017
This adds steps to make clients that have creator browsing contexts to
inherit the active service worker from their creators. While they have
an initial inherited active service worker, if one exists, navigation
matching still always wins. So, if the navigation goes through HTTP
fetch, the inherited active service worker is replaced by the matched
result. Also, if an iframe has a sandbox attribute set without
allow-same-origin token, the inherited active service worker is set to
null.

Related issue: w3c/ServiceWorker#765.
@yoavweiss
Copy link

@yoavweiss yoavweiss commented May 16, 2018

Was there any progress made on this issue?

@wanderview
Copy link
Member

@wanderview wanderview commented May 16, 2018

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

jungkees added a commit that referenced this issue Aug 5, 2019
This change makes it clear that this behavior needs to be (and will be)
specified normatively in HTML Standard, and any future changes for Service
Workers will be incorporated into Service Workers Nightly. It also clarifies,
non-normatively, the behavior of how a service worker client's active service
worker is determined.

Issue: #765.
This moves the issue to the next milestone.
@isubasinghe
Copy link

@isubasinghe isubasinghe commented Aug 8, 2019

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 added a commit that referenced this issue Aug 9, 2019
This change makes it clear that this behavior needs to be (and will be)
specified normatively in HTML Standard, and any future changes for Service
Workers will be incorporated into Service Workers Nightly. It also clarifies,
non-normatively, the behavior of how a service worker client's active service
worker is determined.

Issue: #765.
This moves the issue to the next milestone.
@jungkees
Copy link
Collaborator

@jungkees jungkees commented Aug 9, 2019

Move this to the next milestone with 2183f5e. We'll work on the normative definition of the active service worker determination in HTML Standard and Service Worker Nightly.

@jungkees jungkees removed this from the Version 1 milestone Aug 9, 2019
@jungkees jungkees added this to the Version 2 milestone Aug 9, 2019
@jungkees
Copy link
Collaborator

@jungkees jungkees commented Aug 10, 2019

@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
Copy link

@isubasinghe isubasinghe commented Aug 10, 2019

@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
Copy link

@zkrige zkrige commented Sep 18, 2019

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

@kevodwyer
Copy link

@kevodwyer kevodwyer commented Oct 26, 2019

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/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet