Re: [crx] Opening and writing to a new window from a sandbox page

100 views
Skip to first unread message

Adam Barth

unread,
Feb 15, 2013, 12:59:30 PM2/15/13
to Henry Feild, Chromium-extensions
Yeah, I think the problem is that your iframe is sandboxed and
therefore unable to access the popup. Unfortunately, that's necessary
because otherwise the iframe could break out of the sandbox. :(

Adam


On Tue, Feb 12, 2013 at 11:56 AM, Henry Feild <haf...@gmail.com> wrote:
> Hi,
>
> I have a sandboxed page (specified in my manifest) which is loaded into an
> iframe in my extension's background page. From within my sandboxed page, I'd
> like to open a new window and write to it, i.e.:
>
> var win = window.open(); win.document.write('<p>Hello!</p>');
>
> This works from my extension's background page and from regular web pages,
> but when invoked from either content scripts or my sandboxed page, the
> window opens, but I cannot access the win object (it's defined, but
> empty---console.log outputs "Window {}").
>
> I assume this is due to same-origin policies (with every window being given
> a uinque-origin within the sandboxed environment) . However, since the
> window opens an about:default page, I'm confused why this would matter.
>
> Is this a feature? Is there a parameter I can add to my manifest to avoid
> this? And does anyone know of work-arounds that don't involve using
> postMessage back to my background page? My ideal solution is to have my
> sandboxed script open a new window and interact with it directly, not with
> message passing.
>
> I can provide a full example if necessary, but I'm hoping someone might just
> know off the top of their head. I'm running Chrome 24.0.1312.57 on Mac and
> 24.0.1312.68 on Ubuntu if that helps.
>
> Thanks,
> Hank
>
> --
> You received this message because you are subscribed to the Google Groups
> "Chromium-extensions" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to chromium-extens...@chromium.org.
> To post to this group, send email to chromium-...@chromium.org.
> Visit this group at
> http://groups.google.com/a/chromium.org/group/chromium-extensions/?hl=en.
> For more options, visit
> https://groups.google.com/a/chromium.org/groups/opt_out.
>
>

Adam Barth

unread,
Feb 15, 2013, 1:58:31 PM2/15/13
to Henry Feild, Chromium-extensions
[re-adding chromium-extensions at Henry's request]

I definitely understand your perspective, but the problem is that the
popup window itself needs to be sandboxed (just like iframes inside
the sandboxed iframe need to be sandboxed). If the popup wasn't
sandboxed, then the iframe could escape the sandbox by creating
popups.

As a consequence of being sandboxed, the popup has a unique origin,
regardless of whether it's showing about:blank or some other URL. A
"unique" origin, by nature, is different from every other origin
(that's what makes it unique). That's why you can't script it from
the original iframe: the two are in different unique origins.

Now, we could have made a special exception for about:blank popup
because about:blank documents normally inherit their origin from their
creator. There was a discussion about this in the standards working
group, and folks felt it was better to have a consistent sandboxing
policy rather than have special exceptions for corner cases. That
strengthens the security of the sandbox at the cost of some
functionality.

It's possible we should revisit this question, but we'd want to do
that together with the working group so all the browsers end up
working the same way.

Adam


On Fri, Feb 15, 2013 at 10:42 AM, Henry Feild <haf...@gmail.com> wrote:
> Thanks, Adam. Could you elaborate on the circumstances in which an opened
> about:blank window could break out of the sandbox?
>
> The behavior I'd expect is that the opened window pointing to about:blank
> should share the same unique origin as the caller, and so would simply be an
> extension of the sandbox with no additional privileges. If the about:blank
> popup is then directed to another page (programmaticly or via user action),
> then the win object back in the sandbox would loose it's properties -- just
> like when you create a popup from a regular old web page. I see
> about:blank as the single edge case where a window opened from within a
> sandbox would not be given a new unique origin signature (I'm assuming
> that's the underlying implementation of sandboxing).
>
> I understand that the sandbox shouldn't be able to access windows that load
> content from elsewhere, including pages that would normally be same-origin,
> such as those packaged with my extension -- that's why it's a sandbox, after
> all. But as long as about:blank window are treated the same as the original
> sandbox window, I don't see the security risk. Is this a fair point? Or am
> I off my rocker? :)
>
> -Hank

Henry Feild

unread,
Feb 15, 2013, 2:19:48 PM2/15/13
to Adam Barth, Chromium-extensions
Thanks, Adam.  If the issue does get raised again at a standards working group meeting, the use case I have in mind where adding in the edge case exception is beneficial is when you want a persistent sandbox (i.e.., resides in the background) that can interact with the user via window objects directly.   Of course, I'm not sure that would sway the security gurus :).

-Hank

Adam Barth

unread,
Feb 15, 2013, 2:37:24 PM2/15/13
to Henry Feild, Chromium-extensions
Have you considered using a data URL? That's generally better than
calling document.write in the popup:

window.open("data:text/html,<h1>Hi!</h1>");

Adam

Henry Feild

unread,
Feb 15, 2013, 3:32:43 PM2/15/13
to Adam Barth, Chromium-extensions
I have, but I think I still run into problems. If there is data in my sandbox that I need to do something with based on a user action,  post a message back to my background page to have it save something (or what have you), and then send some updated data back to the opened window, then I don't believe I have a way of doing that. Since:

var win = window.open("data:text/html,<h1>Hi!</h1>"); 

gives me an empty win object, I can't do win.postMessage(...), and I assume that I can't do opener.postMessage(...) from within win, either.

I suppose what I really want is the functionality of an arbitrary web page (so it can perform eval() and open/access dynamic windows, but can't access the extension api), but is persistant and can still post messages (or somehow communicate) back to the extension. My interest in sandboxing is really just in pursuit of this goal. 

I actually just tried loading my sandboxed html from a server rather than from my extension (with sandboxing turned off) -- still embedded within an iframe in my background page. That seems to work as expected. So, I'd like to mimic that functionality, but loading a page from my extension rather than loading one from a server.

-Hank

Adam Barth

unread,
Feb 15, 2013, 6:08:55 PM2/15/13
to Henry Feild, Chromium-extensions
On Fri, Feb 15, 2013 at 12:32 PM, Henry Feild <haf...@gmail.com> wrote:
> I have, but I think I still run into problems. If there is data in my
> sandbox that I need to do something with based on a user action, post a
> message back to my background page to have it save something (or what have
> you), and then send some updated data back to the opened window, then I
> don't believe I have a way of doing that. Since:
>
> var win = window.open("data:text/html,<h1>Hi!</h1>");
>
> gives me an empty win object, I can't do win.postMessage(...), and I assume
> that I can't do opener.postMessage(...) from within win, either.

Hum... That's not what I would expect to happen. I'm not sure why
you're getting an empty win object.

> I suppose what I really want is the functionality of an arbitrary web page
> (so it can perform eval() and open/access dynamic windows, but can't access
> the extension api), but is persistant and can still post messages (or
> somehow communicate) back to the extension. My interest in sandboxing is
> really just in pursuit of this goal.
>
> I actually just tried loading my sandboxed html from a server rather than
> from my extension (with sandboxing turned off) -- still embedded within an
> iframe in my background page. That seems to work as expected. So, I'd like
> to mimic that functionality, but loading a page from my extension rather
> than loading one from a server.

That makes sense. The problem is by including the page in your
extension, it's granted more privileges than you want. The mechanism
we have for dropping those privileges is more general that what you're
looking for, which means it doesn't make exactly the set of trade-offs
that you would like.

Henry Feild

unread,
Feb 16, 2013, 8:19:50 AM2/16/13
to Adam Barth, Chromium-extensions
Concerning window.open("data:..."), I tried the following from within the sandbox:

     var win = window.open(
            "data:text/html,<html><head>"+
            "<script>window.addEventListener('message', function(e){console.log(e)});</script>"+
            "</head><body onload=\"console.log(opener)\"><h1>Hi!</h1></body></html>");
     console.log(win); 
     console.log(win.postMessage); 
     setTimeout(function(){win.postMessage("hello!", '*');}, 3000);

win and win.postMessage are printed as follows:

    console.log(win) --> Window {}
    console.log(win.postMessage) --> function () { [native code] }

So I was wrong about win being empty -- it just appears that way via console.log. However, on the opened window side, I never receive the message sent from the sandbox and opener is null, so postMessage isn't available.  Is the code above reasonable? Or did I leave something out?

Thanks,
Hank

Henry Feild

unread,
Feb 16, 2013, 10:47:05 AM2/16/13
to Adam Barth, Chromium-extensions
Okay, I think I've found a work around using a data:text/html url -- this is probably what you meant earlier, but I was only thinking of using it within a sandbox, rather than in a background page directly.  In my background page, I specify an empty iframe like so:

<iframe id="myframe"></iframe>

Then in one of my startup scripts, once I know my extension's path, I set the src url of the iframe to 'data:text/html,....', using the extension path in the embedded <script src=...> tags, etc. This is where I'm sticking the entirety of the page I was formally sandboxing, and the same one I was having success with by loading from a server.  The data: url apparently gives the generated page a unique origin, so the page appears that it loaded from elsewhere.  

Just as when I loaded the page from a server, this appears to be allowing me to use eval(), open/access new widows, communicate via postMessage with my background page,  but can't, as far I can tell, access any of the extension apis (chrome.extension and chrome.windows are both undefined) -- perfect! 

So, that apparently solves my issue. Whew.  Do you see any issus with this?

Thanks for your help,
Hank

Adam Barth

unread,
Feb 16, 2013, 1:02:01 PM2/16/13
to Henry Feild, Chromium-extensions
Yeah, that sounds like a good way to address your use case. I'm glad
that works for you.

Adam
Reply all
Reply to author
Forward
0 new messages