How to execute JS before other scripts on a page in a Chrome Extension?

In my Chrome extension (manifest v3), I want my script to run first on the page and override some native window functions before any other scripts on the webpage can access them.

I have contentscript.js set with run_at = document_start, and it successfully injects script.js into the page’s DOM. However, I can’t guarantee that my script will run before the webpage’s own scripts.

I’ve tried different approaches, but none have worked. How can I solve this issue?

Thomas Verhoeven

6 months ago

4 answers

103 views

Rating

00
Answer

Answers

Andreas Hansen

6 months ago

1 comment

Rating

00

If you need more control over when and how your script executes, you can use a MutationObserver to monitor changes in the document and adjust the execution of other scripts before they activate. This can help when directly injecting scripts into the DOM doesn’t resolve the issue with execution order.

Reply

    Álvaro Ruiz

    6 months ago

    Rating

    00

    Honestly, this raises a bit of concern.

    Changing native window functions before other scripts load could be used for malicious purposes. For example, this could intercept user data, alter page content, or bypass website protections. While these techniques can be useful for things like ad-blocking, if used improperly, they can be harmful to users.

    Reply

Roberto Greco

6 months ago

Rating

00

Another approach is to inject a element directly into the DOM via the content script:

		
const scriptEl = document.createElement("script"); scriptEl.type = 'module'; // Use 'module' if you're working with ES modules scriptEl.src = chrome.runtime.getURL('./main-world.js'); (document.head || document.documentElement).appendChild(scriptEl);

To make this work, add main-world.js to the web_accessible_resources section in manifest.json:

		
"web_accessible_resources": [ { "resources": ["main-world.js"], "matches": [""] } ]

Now, you can modify the window object directly in the page’s context.

For example, here’s how you can override alert in main-world.js:

		
const originalAlert = window.alert; window.alert = function(msg) { console.log(msg); // Do something with the message originalAlert(msg); // Pass the message to the original alert function };

Reply

Alessandro Gallo

6 months ago

Rating

00

The main reason your content script can’t modify the window object directly on the webpage is because of the "isolated world" of content scripts. By default, content scripts run in a separate execution context, meaning they cannot directly modify objects in the main page’s context.

To run your script in the main context, you can specify this in manifest.json like this:

		
"content_scripts": [ { "matches": [""], "js": ["src/my_content_script.js"], "run_at": "document_start", "world": "MAIN" } ]

Reply