0

Overview

This MutationObserver Wrapper should be able to provide developers with any changes that have been made in the DOM for security reasons.

Problem

I need a simple way to create a wrapper for MutationObserver. I just want to be informed when a MutationObserver was created on the page. Then I want to make sure the code runs before all other codes so that I can put it in an extension.

Code

This is what I tried:

 const dump = console.log.bind(console); class Observer { static started = false static jacked = {} static start() { Observer.started = true; Observer.hijack( MutationObserver, function constructor() { alert("CAREFUL!! - MutationObserver is running here!"); return (Observer.jacked.MutationObserver).constructor.apply(this, [...arguments]); }); // if (!Observer.fixes[document.domain]) // { // dump("not listining on: "+document.domain); // return; // }; // // Observer.fixes[document.domain]() } static hijack(target, impose) { let waiting = setInterval(()=> { if ((typeof target.prototype) !== "object"){ return }; if ((typeof target.prototype.constructor) !== "function"){ return }; clearInterval(waiting); let name = target.prototype.constructor.name; dump("hijacking: "+name); Observer.jacked[name] = target; Object.defineProperty(target.prototype, "constructor", {writable:false, configurable:false, enumerable:false, value:impose}); },0); } let waiting = setInterval(() => { let exists = ((typeof MutationObserver) !== "undefined"); if ( !exists ) { console.log("observer waiting for `MutationObserver`"); return }; if ( Observer.started ) { clearInterval(waiting); console.log("observer already started .. exiting"); return }; clearInterval(waiting); Observer.start(); }, 0); 
3
  • I don't get why you expect typeof MutationObserver to be "undefined"? Commented Feb 4, 2023 at 19:44
  • 1
    I don't get what the problem is or what you are trying to do. Also what do you mean by "for security reasons"? Where does this code execute, and what is it supposed to guard against? What is your threat model? Commented Feb 4, 2023 at 19:46
  • It's unclear what the problem is aside from this code being overengineered. Note that in an extension you'll need to run this code in page context (Chrome) or via wrappedJSObject + exportFunction (Firefox). Commented Feb 5, 2023 at 11:43

1 Answer 1

1

Try something like this, however, be aware of what globalThis refers to in your extension:

 const jacked = {}; jacked.MutationObserver = globalThis.MutationObserver; delete globalThis.MutationObserver; globalThis.MutationObserver = (class MutationObserver { constructor() { console.log("jacked"); } observe() { console.log("busy"); } }); 

after running the above, anywhere, like in a function, you can test if your wrapper-test works like this:

 let watcher = (new MutationObserver(function(){})); watcher.observe(); 

You can use jacked to resume normal operation inside your supplementary class constructor by returning a new jacked.MutationObserver.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.