intercept / proxy window.postMessage

Viewed 444

In my app, we are using a third party analytics library, which, apart from other things, is also using postMessage to post some info to the parent window (possibly for iframe use cases for the analytics library).

In our case, this info is sensitive and we do not want to send it to parent window (if our app is opened in an iframe or as a child window by someone) as we wouldn't have any control over what the parent window does with this information (even for valid parents). There is no configuration in the library to switch off this functionality.

As a potential solution, we figured out that if we can intercept all postMessages being sent out to the parent window and just filter this message , it would solve our purpose for now. To achieve this, I have been looking at proxying window.postMessage or redefining the method for adding this validation.

I am just trying to understand if this is feasible, and how?

  • is it possible from the current window to override the parentWindow.postMessage (or for that matter, override a childWindow.postMessage?)

What have i tried so far:

From window A, I am opening a window B, and then sending a postMessage from windowA to windowB. (This requires a reference to windowB in windowA, so that I can do windowB.postMessage)

If I proxy window.postMessage, it is not intercepting the windowB.postMessage call. If I proxy windowB.postMessage, it is intercepting the windowB.postMessage call.

I am just trying to understand if the same can work for parentWindow, and what are the other constraints (same origin, etc)

codesandbox link: https://codesandbox.io/s/postmessage-forked-slv9b?file=/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Static Template</title>
  </head>
  <body>
    <input class="s" type="text" />
    <button class="s">send</button>
    <script>
      const handler = {
        apply: function (target, thisArg, argumentsList) {
          console.log(`window post message proxy: ${argumentsList[0]}`);

          return target(...argumentsList);
        }
      };

      const write = (str) =>
        document.body.insertAdjacentHTML("beforeend", str + "<br>");
      write("<hr>");
      // --
      const windowFeatures =
        "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes";
      /** @type { Window | undefined } */
      let subWindow;
      /** @type { HTMLButtonElement } */
      const button = document.querySelector("button.s");
      /** @type { HTMLInputElement } */
      const input = document.querySelector("input.s");
      button.onclick = () => {
        if (!subWindow) {
          subWindow = window.open("/reciver.html", "shipping", windowFeatures);
          setTimeout(() => {
            // THIS HANDLING HERE
            subWindow.postMessage = new Proxy(subWindow.postMessage, handler);
            subWindow.postMessage(input.value, window.location.origin);
          }, 3000);
        } else {
          subWindow.postMessage(input.value, window.location.origin);
        }
        write(input.value);
      };
    </script>
  </body>
</html>
0 Answers
Related