瀏覽代碼

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.
Luke Wilde 8 月之前
父節點
當前提交
079c28d5e6

+ 3 - 1
Libraries/LibWeb/HTML/MessagePort.cpp

@@ -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

+ 1 - 0
Libraries/LibWeb/HTML/Window.cpp

@@ -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);
     }));
 

+ 2 - 0
Tests/LibWeb/Text/expected/HTML/MessagePort-MessageEvents-should-be-trusted.txt

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

+ 2 - 0
Tests/LibWeb/Text/expected/HTML/Window-MessageEvents-should-be-trusted.txt

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

+ 29 - 0
Tests/LibWeb/Text/input/HTML/MessagePort-MessageEvents-should-be-trusted.html

@@ -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>

+ 27 - 0
Tests/LibWeb/Text/input/HTML/Window-MessageEvents-should-be-trusted.html

@@ -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>