LibWeb: Make MessageEvents from {Window,MessagePort}.postMessage trusted

The MessagePort one in particular is required by Cloudflare Turnstile,
as the method it takes to run JS in a worker is to `eval` the contents
of `MessageEvent.data`. However, it will only do this if
`MessageEvent.isTrusted` is true, `MessageEvent.origin` is the empty
string and `MessageEvent.source` is `null`.

The Window version is a quick fix whilst in the vicinity, as its
MessageEvent should also be trusted.
This commit is contained in:
Luke Wilde 2024-11-15 17:15:34 +00:00 committed by Andreas Kling
parent f87041bf3a
commit 079c28d5e6
Notes: github-actions[bot] 2024-11-15 17:51:05 +00:00
6 changed files with 64 additions and 1 deletions

View file

@ -408,7 +408,9 @@ void MessagePort::post_message_task_steps(SerializedTransferRecord& serialize_wi
MessageEventInit event_init {};
event_init.data = message_clone;
event_init.ports = move(new_ports);
message_event_target->dispatch_event(MessageEvent::create(target_realm, HTML::EventNames::message, event_init));
auto event = MessageEvent::create(target_realm, HTML::EventNames::message, event_init);
event->set_is_trusted(true);
message_event_target->dispatch_event(event);
}
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-start

View file

@ -1165,6 +1165,7 @@ WebIDL::ExceptionOr<void> Window::window_post_message_steps(JS::Value message, W
message_event_init.ports = move(new_ports);
auto message_event = MessageEvent::create(target_realm, EventNames::message, message_event_init);
message_event->set_is_trusted(true);
dispatch_event(message_event);
}));

View file

@ -0,0 +1,2 @@
ping
pong

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<script>
asyncTest((done) => {
const workerJs = `
self.onmessage = (messageEvent) => {
if (messageEvent.isTrusted && messageEvent.origin === '' && messageEvent.source === null) {
self.postMessage(messageEvent.data + "pong");
}
};
`;
const workerJsBlob = new Blob([workerJs], {
type: "text/javascript",
});
const workerJsUrl = URL.createObjectURL(workerJsBlob);
const worker = new Worker(workerJsUrl);
worker.onmessage = (messageEvent) => {
if (messageEvent.isTrusted && messageEvent.origin === '' && messageEvent.source === null) {
println(messageEvent.data);
done();
}
};
worker.postMessage("ping\n");
});
</script>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<script>
asyncTest((done) => {
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const script = iframe.contentDocument.createElement("script");
script.textContent = `
self.onmessage = (messageEvent) => {
if (messageEvent.isTrusted && messageEvent.source === window.parent) {
window.parent.postMessage(messageEvent.data + "pong");
}
};
`;
iframe.contentDocument.body.appendChild(script);
window.onmessage = (messageEvent) => {
if (messageEvent.isTrusted && messageEvent.source === iframe.contentWindow) {
println(messageEvent.data);
done();
}
}
iframe.contentWindow.postMessage("ping\n", { targetOrigin: "*" });
});
</script>