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

sandboxed iframe #199

Open
hatemhosny opened this issue Jan 1, 2024 · 2 comments
Open

sandboxed iframe #199

hatemhosny opened this issue Jan 1, 2024 · 2 comments

Comments

@hatemhosny
Copy link

hello,
Thanks for the great project. I used it as a base for Vue support on my project (LiveCodes - an open-source client-side code playground for 80+ frameworks/languages).
https://livecodes.io/?template=vue

I noticed that the result page of the repl is displayed in a sandboxed iframe. However, the code is sent to the iframe by setting srcdoc. This does not set a different origin for the iframe.

Note, however, that you need to be very careful when dealing with framed content that comes from the same origin as the parent. 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.
https://web.dev/articles/sandboxed-iframes

For example, if I run this in the repl, it works!

parent.document.body.innerHTML = 'Hacked!'

If we are able to access the repl parent (embedding pages on user websites), then we can read cookies, localStorage and all sorts of bad things. I think this is a major security concern.

I suggest to set the iframe.src to a page on a different origin and then send the html using postMessage.
This is an example repo, where I added a simple webpage that can be set as iframe.src and would accept the HTML sent to it from its parent and document.writes it to itself. I published that to npm so that it can be hosted (with versions) on CDNs. It can be used as this URL: https://unpkg.com/@live-codes/[email protected]/index.html.

That was just an example. However, if you agree with that, I would be happy to send a PR for this change.

@tachibana-shin
Copy link

Instead of using the document.write api which has been removed by Google, we can use service worker to thoroughly handle this.

@hatemhosny
Copy link
Author

Thank you @tachibana-shin for drawing my attention to this. I did find what you refer to: https://developer.chrome.com/blog/removing-document-write
However, I believe this does not apply to our case:

Specifically Chrome will not execute the <script> elements injected via document.write() when all of the following conditions are met:
...
2. The document.write() is in a top level document. The intervention does not apply to document.written scripts within iframes as they don't block the rendering of the main page.
...

In this case we execute document.write in the iframe, so we are good to go.

Note that document.write triggers page events like load and DOMContentLoaded. So users can use these as usual.

This is a much simpler solution than having to manage and maintain a service worker for the output page. In addition, using a service worker will require injecting code that handles it in user code, which is something we should aim to avoid if we can.

Anyway, regardless of the way we send the code, I think the main goal is to properly sandbox the iframe by keeping the page on a separate origin.

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

No branches or pull requests

2 participants