Skip to content

Conversation

@bloodyowl
Copy link
Collaborator

When treating a foreign object (such as a frame window), access throws.

When treating a foreign object (such as a frame window), access throws.
@bobzhang
Copy link
Member

bobzhang commented Jul 9, 2020

do you have more context so that we can tell it's a mis-use or not?
This unsafe function should be guarded that the input can not be null/undefined so that it should not throw

@bloodyowl
Copy link
Collaborator Author

When manipulating another frame's window that has a different domain, only some of its fields are accessible (e.g. postMessage), and the other throw:
https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl

I have some code that generates Caml_option.some(window.parent), which throws because it tries to access BS_PRIVATE_NESTED_SOME_NONE. The previous method worked by chance, as it used to check the 0 property to compare it to undefinedHeader, andforeingWindow[0] is accessible without a security error.

@bobzhang
Copy link
Member

bobzhang commented Jul 10, 2020 via email

@bloodyowl
Copy link
Collaborator Author

IIUC -- for some object called o, even if it's not null/undefined, o.some_random_property will still be raised for security reasons, is that correct?

That's right. For these objects, only a certain list of properties are accessible without having an error being thrown.

do you have some cleaner patches in mind

We could check if the object is a window, but that seems a bit too specific.

Something like:

let isNested (x : Obj.t) : bool = (Obj.magic x)##window != x && (* false if the object is of window type *) Obj.repr ((Obj.magic x : nested).depth) != Obj.repr Js.undefined
@bloodyowl
Copy link
Collaborator Author

@bobzhang After giving it some thoughts, I think the try catch approach seems a bit more solid as it can cover some edge cases with ES6 proxies too

@bobzhang
Copy link
Member

bobzhang commented Jul 14, 2020 via email

@bobzhang
Copy link
Member

bobzhang commented Jul 14, 2020 via email

@bloodyowl
Copy link
Collaborator Author

instanceof wouldn't work in my case cause the window object isn't an instance of the Window BS has access to. Optional chaining would fail (at least the polyfill would for sure).

@bloodyowl
Copy link
Collaborator Author

@bobzhang do you have some other solution in mind?

@bobzhang
Copy link
Member

bobzhang commented Jul 29, 2020 via email

@bobzhang
Copy link
Member

bobzhang commented Aug 1, 2020

hi @bloodyowl I cloned the repo, followed the instructions but could not reproduce such things. What I need is simple(does not have to contain ml code), a single html with iframe to demonstrate the security issues, thanks

@bloodyowl
Copy link
Collaborator Author

@bobzhang:

<!DOCTYPE html> <html> <iframe id="frame" src="https://bucklescript.github.io"></iframe> <script> document.querySelector("#frame").addEventListener("load", () => { console.log("that's ok:") console.log( document.querySelector("#frame").contentWindow.postMessage ); console.log("that's not:") console.log( document.querySelector("#frame").contentWindow.BS_PRIVATE_NESTED_SOME_NONE ); }); </script> </html>
@bobzhang
Copy link
Member

bobzhang commented Aug 2, 2020

thanks for the example, now I have a better understanding what's going on.
It seems the root is the same origin policy. if it is the same origin, it works fine.
Screenshot 2020-08-02 at 3 49 11 PM

If it is not the same origin, even this will raise (without even accessing the window):

 console.log( document.querySelector("#frame").contentWindow ); 

This is a very niche area and cross origin iframe is some thing you should be careful

@bloodyowl
Copy link
Collaborator Author

Yeah I'm aware of the limitations and I know what I'm doing 😄

If it is not the same origin, even this will raise (without even accessing the window):

 console.log( document.querySelector("#frame").contentWindow ); 

That'll raise only because you're not immediately accessing an authorised property (such as postMessage).

The issue is that now, the Caml_option code, without me wanting to, accesses properties that aren't authorised, hence the try/catch proposal.

@bobzhang
Copy link
Member

bobzhang commented Aug 3, 2020

@bloodyowl this is a niche case when do the cross origin iframe. There are lots of workaround, like instead of wrapping it as an option, you can wrap it using `Some. I think the benefit does not justify the slow down for Caml_option.some everywhere. Let me know if you have other reasons not mentioned

@bobzhang bobzhang closed this Aug 3, 2020
@bloodyowl
Copy link
Collaborator Author

@bobzhang It's a bit more inconvenient than what you describe (as It also prevents me from passing it directly in an optional labeled arguments) but I get it. I hope that'll be reconsidered some day 🙂

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

Labels

None yet

2 participants