You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Accessing contentWindow on cross domain iframes with static js interop doesn't work #54938
A security exception is thrown when trying to access the contentWindow property of a cross domain iframe using static interop:
frame.contentWindow!.postMessage(...)
Given the same setup using non static interop, the call succeeds:
(frame as html.IFrameElement).contentWindow!.postMessage(...)
It blows up here in the rtti:
default:// The interceptors for native JavaScript types like bool, string, etc.// (excluding number and function, see above) are stored as a symbolized// property and can be accessed from the native value itself.
classRef =JS('', '#[#]', obj, _extensionType);
With this message:
Uncaught DOMException: Failed to read a named property from 'Window': Blocked a frame with origin "http://localhost:8002" from accessing a cross-origin frame.
at Object.getInterceptorForRti (http://localhost:8002/dart_sdk.js:12719:27)
at dart_rti.Rti.new._isTestViaProperty (http://localhost:8002/dart_sdk.js:24534:28)
at dart_rti.Rti.new._generalNullableIsTestImplementation (http://localhost:8002/dart_sdk.js:24525:24)
at dart_rti.Rti.new._generalNullableAsCheckImplementation (http://localhost:8002/dart_sdk.js:24563:28)
at Object.getProperty (http://localhost:8002/dart_sdk.js:71713:18)
...
at internalCallback (http://localhost:8002/dart_sdk.js:37398:11)
It appears something about the rtti check is accessing a property that is locked down on cross domain frames when trying to get the Window object, but I'm unable to step deeper into the stack in the devtools to see exactly the property that is being checked.
cc @nshahan@fishythefish - I believe this wouldn't affect the dart2js compiler due to differences in how we lookup the interceptor there, but it's worth checking nonetheless.
So it is checking to see if it is a dart object or a js object, but that can't be done without an exception being thrown on the Window object since it is cross domain. Perhaps the an exception looking up the symbol could be handled and then the symbol set to null in the catch for a minimal performance penalty so it only happens first time around?
@sigmundch I agree with your assessment. The code referenced here is only run in DDC. If dart2js has a problem finding the interceptor for cross origin values it will need to be addressed separately. Would dart2js allow for apps from different frames to pass Dart values between them or are they forced to do some type of conversion to a JavaScript interop value first?
If there isn't any Dart to Dart object passing allowed then in DDC it seems like the right thing to do here is to treat any cross origin value as a LegacyJavaScriptObject. We just need to find the right way to test for that as efficiently as possible.
precisely - I think treating it as JSObject makes sense.
Anything sent between separate apps (whether they are on the same page or separate iframes) will need to go through interop, and as a result is treated as JS values. Even if you send raw unboxed value through the interop boundary (bypassing some interop conversions), all RTI data is isolated, so it will be viewed as a JS object.
The sidebar (part of Flutter DevTools) is hosted inside a sandboxed iframe in VS Code and trying to communicate with its parent using window.parent?.postMessage
If this isn't a simple fix, are there any reasonable workarounds we could apply to that code?
That issue seems more like #54443 considering it's dart2js, but it's a similar issue around cross-domain frames. The error seems to arise from _generalNullableAsCheckImplementation, indicating there's a downcast with a nullable type.
Looking at the source I wonder if it's parent?.postMessage triggering this. Parker is using a workaround with getProperty to work around this. Maybe that can help here too, but I'll need to look at the JS code to determine which part is the issue. Is there a good way to repro this and get the sources?
@srujzs you can repro this using VS Code and Flutter master (just try to load the Flutter Sidebar), but it's probably not very easy to debug that way (however I don't know if it can easily be reproduced outside of it because of the sandboxed iframe etc.).
You can click Help -> Toggle Developer Tools in VS Code to open the Chrome DevTools.
Yeah, I don't see a usable workaround for this like we had with the Window wrapper in dart:html that wrapped dynamic. I'll work on seeing if we can get a wrapper like that in package:web next.
@srujzs and I talked about this earlier. We've prioritized finding a solution here.
We want to make sure that it's an separate opt-in API for cases where a user knows they might be dealing with a x-domain object. Given the need for extra interceptor logic/a wrapper we want to make sure we don't degrade other interop use cases.
Activity
dart-github-bot commentedon Feb 16, 2024
area-dart-cli(medium confidence)(what's this?)
sigmundch commentedon Feb 16, 2024
cc @nshahan @fishythefish - I believe this wouldn't affect the dart2js compiler due to differences in how we lookup the interceptor there, but it's worth checking nonetheless.
jezell commentedon Feb 16, 2024
Can repro similar behavior in JS trying to access properties that don't exist on a cross domain iframe.
however
So it is checking to see if it is a dart object or a js object, but that can't be done without an exception being thrown on the Window object since it is cross domain. Perhaps the an exception looking up the symbol could be handled and then the symbol set to null in the catch for a minimal performance penalty so it only happens first time around?
nshahan commentedon Feb 16, 2024
@jezell Thanks for the helpful report!
@sigmundch I agree with your assessment. The code referenced here is only run in DDC. If dart2js has a problem finding the interceptor for cross origin values it will need to be addressed separately. Would dart2js allow for apps from different frames to pass Dart values between them or are they forced to do some type of conversion to a JavaScript interop value first?
If there isn't any Dart to Dart object passing allowed then in DDC it seems like the right thing to do here is to treat any cross origin value as a
LegacyJavaScriptObject. We just need to find the right way to test for that as efficiently as possible.sigmundch commentedon Feb 16, 2024
cc @rakudrama
precisely - I think treating it as JSObject makes sense.
Anything sent between separate apps (whether they are on the same page or separate iframes) will need to go through interop, and as a result is treated as JS values. Even if you send raw unboxed value through the interop boundary (bypassing some interop conversions), all RTI data is isolated, so it will be viewed as a JS object.
srujzs commentedon Feb 16, 2024
Similar issue: #54443. It's possible we may come across other issues here even if this specific bug is fixed in the RTI.
DanTup commentedon Mar 27, 2024
The Flutter sidebar in VS Code is failing with what seems like the same error:
Dart-Code/Dart-Code#5049
The sidebar (part of Flutter DevTools) is hosted inside a sandboxed iframe in VS Code and trying to communicate with its parent using
window.parent?.postMessageIf this isn't a simple fix, are there any reasonable workarounds we could apply to that code?
jezell commentedon Mar 27, 2024
@DanTup As a workaround, I believe you can cast to the old dart:html version which doesn't have the problem.
Switch back to dart:html for postMessage
srujzs commentedon Mar 27, 2024
That issue seems more like #54443 considering it's dart2js, but it's a similar issue around cross-domain frames. The error seems to arise from
_generalNullableAsCheckImplementation, indicating there's a downcast with a nullable type.Looking at the source I wonder if it's
parent?.postMessagetriggering this. Parker is using a workaround withgetPropertyto work around this. Maybe that can help here too, but I'll need to look at the JS code to determine which part is the issue. Is there a good way to repro this and get the sources?DanTup commentedon Mar 27, 2024
@srujzs you can repro this using VS Code and Flutter master (just try to load the Flutter Sidebar), but it's probably not very easy to debug that way (however I don't know if it can easily be reproduced outside of it because of the sandboxed iframe etc.).
You can click Help -> Toggle Developer Tools in VS Code to open the Chrome DevTools.
I'll see if getProperty helps.
1 remaining item
DanTup commentedon Mar 27, 2024
Oh by the way, you can get at the source from your Flutter SDK checkout (be on master, not stable):
flutter\bin\cache\dart-sdk\bin\resources\devtools\main.dart.js(let me know if I should move this to another issue since it sounds like it might not be the same)
For convenience, here's the bit of code I suspect you care about:
srujzs commentedon Mar 27, 2024
(following up in flutter/devtools#7476 - thanks for all the details!)
jezell commentedon Aug 8, 2024
This is still blocking us from being able to move to package:web.
mraleph commentedon Aug 8, 2024
Can we bump priority of fixing this? cc @natebiggs
srujzs commentedon Aug 8, 2024
Yeah, I don't see a usable workaround for this like we had with the
Windowwrapper indart:htmlthat wrappeddynamic. I'll work on seeing if we can get a wrapper like that inpackage:webnext.biggs0125 commentedon Aug 8, 2024
@srujzs and I talked about this earlier. We've prioritized finding a solution here.
We want to make sure that it's an separate opt-in API for cases where a user knows they might be dealing with a x-domain object. Given the need for extra interceptor logic/a wrapper we want to make sure we don't degrade other interop use cases.
Add cross-origin window and location wrappers
Add cross-origin window and location wrappers (dart-lang#291)