UNPKG

3.46 kBJavaScriptView Raw
1/**
2 * Copyright 2017 Google Inc. All Rights Reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 * http://www.apache.org/licenses/LICENSE-2.0
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
12 */
13
14import * as Comlink from "/base/dist/esm/comlink.mjs";
15
16describe("Comlink origin filtering", function () {
17 it("rejects messages from unknown origin", async function () {
18 // expose on our window so comlink is listening to window postmessage
19 const obj = { my: "value" };
20 Comlink.expose(obj, self, [/^http:\/\/localhost(:[0-9]+)?\/?$/]);
21
22 let handler;
23 // juggle async timings to get the attack started
24 const attackComplete = new Promise((resolve, reject) => {
25 handler = (ev) => {
26 if (ev.data === "ready" && ev.origin === "null") {
27 // tell the iframe it can start the attack
28 ifr.contentWindow.postMessage("start", "*");
29 } else if (ev.data === "done") {
30 // confirm the attack failed, the prototype was not updated
31 expect(Object.prototype.foo).to.be.undefined;
32 expect(obj.my).to.equal("value");
33 resolve();
34 }
35 };
36 window.addEventListener("message", handler);
37 });
38 // create a sandboxed iframe for the attack
39 const ifr = document.createElement("iframe");
40 ifr.sandbox.add("allow-scripts");
41 ifr.src = "/base/tests/fixtures/attack-iframe.html";
42 document.body.appendChild(ifr);
43 // wait for the iframe to load
44 await new Promise((resolve) => (ifr.onload = resolve));
45 // and wait for the attack to complete
46 await attackComplete;
47 window.removeEventListener("message", handler);
48 ifr.remove();
49 });
50 it("accepts messages from matching origin", async function () {
51 // expose on our window so comlink is listening to window postmessage
52 const obj = { my: "value" };
53 Comlink.expose(obj, self, [/^http:\/\/localhost(:[0-9]+)?\/?$/]);
54
55 let handler;
56 // juggle async timings to get the attack started
57 const attackComplete = new Promise((resolve, reject) => {
58 handler = (ev) => {
59 if (ev.data === "ready" && ev.origin === window.origin) {
60 // tell the iframe it can start the attack
61 ifr.contentWindow.postMessage("start", "*");
62 } else if (ev.data === "done") {
63 // confirm the attack succeeded, the prototype was updated
64 expect(Object.prototype.foo).to.equal("x");
65 expect(obj.my).to.equal("value");
66 resolve();
67 }
68 };
69 window.addEventListener("message", handler);
70 });
71 // create a sandboxed iframe for the attack, but with same origin
72 const ifr = document.createElement("iframe");
73 ifr.sandbox.add("allow-scripts", "allow-same-origin");
74 ifr.src = "/base/tests/fixtures/attack-iframe.html";
75 document.body.appendChild(ifr);
76 // wait for the iframe to load
77 await new Promise((resolve) => (ifr.onload = resolve));
78 // and wait for the attack to complete
79 await attackComplete;
80 window.removeEventListener("message", handler);
81 ifr.remove();
82 });
83});