Skip to main content

Chrome Extension (part 1): Injecting External Scripts into a Web Page

Recently, I was required to develop a chrome extension for some executives. This plugin only targeted a few of our most visited websites. There was a lot of approaches to implement the extension and all our use cases.
One particular challenge was trying to inject scripts from our own CDN into specific web pages. the scripts were required to interact with the page and all variables possible. Since there is a script isolation thing for Chrome Extensions, I felt this was a good challenge to take up in my spare time.

Here is a sample of my content script.

content.js
document.onreadystatechange = function () {
console.log("document state is:" + document.readyState);
if (document.readyState == "complete") {
let randAntiCache = Math.random().toString().split('.')[1];

let scriptURL4="http://localhost.test/testscript.js?v="+randAntiCache;
let scriptnode4 = document.createElement("script");
scriptnode4.setAttribute("src", scriptURL4);
document.body.appendChild(scriptnode4);
}

}


Even though I had a background script to remove the response Headers I still got the error below.
 After reading so many articles I conclude that this could not be achieved without running chrome from the command line, the good thing about running chrome from the command line is that it allows you to specify that chrome should disable certain security features during startup. So I employed the flags below.

 --allow-running-insecure-content --disable-web-security --disable-gpu --user-data-dir=%LOCALAPPDATA%\Chromium\Temp

In order to make this flag seem like a semi-permanent fix. I created a chrome shortcut on my desktop. right-click on the shortcut and click 'Properties'. and I pasted the long line below into the target field.
C:\Users\XXX\AppData\Local\Chromium\Application\chrome.exe --allow-running-insecure-content --disable-web-security --disable-gpu --user-data-dir=%LOCALAPPDATA%\Chromium\Temp

The path to the chrome application is
C:\Users\XXX\AppData\Local\Chromium\Application\chrome.exe
This path may be different in your case but it will be generated automatically for you when you create a shortcut. you can also obtain it by viewing any chrome shortcut created by your computer during installation.

I double-clicked the newly modified shortcut to start chrome, then I reload the extension and reload the web page. As you can see below, we now have a warning and not the usual error observed moments ago, the script gets loaded as expected and also it is executed within the page.


there are still some other issues encountered that will eventually be solved. For example; the recommended architecture supports that only one script should be injected by the extension's content script. This script is called the father-script(composer.js). the father-script is required to detect the page URL and then append other scripts(e.g theme.js) to the page's body tag, or somehow inject more scripts into the context of the page.

whilst it was easy to inject the father script(composer.js) into the webpage using an extension, the father script could not inject other scripts(theme.js) into the page. the father script was only successful when the webpage had loose content-policy headers defined. the below is a typical scenario where content-policy headers were properly defined.

* composer was injected successfully by the extension, but composer could not inject theme.js


This experimentation shows that it is quite easy to inject scripts into a webpage as an extension developer. But there is enough security to make sure that injected scripts can not inject other scripts.
As you might observe the error obtained is not about mixed content but content security error. if this host never declared the content security or defined it as a wild card, then the second-order injection would have worked.


there are suggestions that the extension should inject the other scripts just as the first was loaded. it is all about flexibility. currently, I am exploring the onHeadersReceived event of the chrome extension for this. the official docs said you can only modify the content policy headers if you specify extra-headers as an option. It also advised that this is a resource-intensive approach. but for me, it is worth trying just for experimentation.

Let me know in the comments how you are handling these situations in your dev ops.
feel free to ask for more clarity in the comment, I might just provide a GitHub link if required.

Comments

Popular Articles

Is this a CSS Bug: setting Background and z-index for Pseudo selectors(::before & :: after)

Recently I was making some UI for a friend's project. We had this CSS button effect that works elsewhere but failed to work at the desired location. Upon troubleshooting, we discovered that if the parent element has a background defined, you can't control the z-index of the pseudo selection of any of its children. Wait for it, I have got some demo. TL;DR set background colour or image for a " DIV.parent ", create a " Div.child " inside the " DIV.parent ". use CSS to modify the " ::before" " element of the " Div.child " as follows; set position as absolute, content as an empty string, height:100% and width is best at 50% for example purposes, lastly, give it a background colour. You will observe that the " ::before" " element is overlaying the actual element's content. Try to adjust the z-index of the " ::before" ". You will also realize that the z-index works fine if we remove the backgroun...

Ubuntu: Unable to get IP for network interface / Using multiple network adapters

This is a very focused article on a similar issue which i encountered very recently. Problem: I recently installed Ubuntu Server 20.0 on a virtualBox. My intention was to use 2 network adapters as shown in the picture below. Host-Only Network NAT After setting up, I realised that i could not get IP address for the NAT adapter and it was always DOWN. Solution: Ubuntu20.0 comes with a different Newtork Configuration System compared to older ones like Ubuntu 14. The new Ubuntu uses netplan to handle network configurations. To solve this issue, you need to add specific information about every adapter into the netplan configuration file. The first adapter will always be configured by default. Follow through this article to learn how in 5 easy steps. 1. The picture below shows that my VM is already configured to use 2 network adapters. 2. Now i powered up the VM and check my network parameters. I powered the VM and ran the commands to check if my 2 network adapters we...

How to configure multiple host for Apache on Ubuntu

Introduction I recently switched to Ubuntu Desktop. Everything was simple and straight forward until i needed to run multiple Laravel projects on my LAMP stack. For the records, I will also demonstrate how i installed a stable LAMP setup. If you are only interested in configuring multiple Host on Apache, you can click here to skip the story. Installing the LAMP Stack LAMP simply means Linux,Apache,MySql,PHP. I tried so many methods but the command below made life easier for the living . sudo apt-get install lamp-server^ The command above installed all i needed without any issue. I already configured Mysql from previous installation. All data and configurations of MySql from previous installation remained intact. I installed the laravel installer and initialized a new Laravel project in the Apache directory. cd /var/www/html At first i was comfortable with using  php artisan ser Later i decided i was not convenient with the 127...:8080, in windows i had laragon to create vanit...