I have a Chrome extension (source provided below) that is getting caught with a race condition. I need some injected JavaScript to run before all other JavaScript on a web page.
The source code of a simple example of what I'm trying to do is here: https://github.com/nddipiazza/oogi
It is attempting to add a namespace to all cookie names that will actually be persisted as cookies, but at the same time remove those namespaces from the cookies that are in use.
So let's say normally without the extension you would have 2 cookies that are saved after accessing a site:
JSESSIONID
lastVisit
This extension would save them as:
oogi$JSESSIONID
oogi$lastVisit
There are basically two major parts to the extension.
https://github.com/nddipiazza/oogi/blob/master/background.js This intercepts the incoming and outgoing http headers so that it can properly add the namespace to the incoming cookies and remove the ones from the outgoing. This way the namespace of the cookie is purely local to us.
https://github.com/nddipiazza/oogi/blob/master/inject.js This intercepts JavaScript cookie get and set operations for the same reason as we do it for the headers.
The problem here is that in order for this to work, I need the javascript cookie header intercepts in inject.js
to absolutely always be loaded before any other javascript. But it doesn't.
Example: Cookies in inline javascript such as:
<body>
<H2>Cookies from Inline JavaScript</H2>
<script>
console.log("Inline javascript is executed.");
document.write(listCookies());
</script>
</body>
Will already load prior to the inject cookie interceptor being loaded. You can tell from the console log will read in this order:
Inline javascript is executed.
cookie get/set injector completed
Is there a way to fix this inject race condition? I want to allow a chrome extension to force a javascript to be run prior to doing any javascript on a page.
A chrome extension is a program that is installed in the Chrome browser that enhances the functionality of the browser. You can build one easily using web technologies like HTML, CSS, and JavaScript. Creating a chrome extension is similar to creating a web application, but it requires a manifest.
JavaScript injection is a process by which we can insert and use our own JavaScript code in a page, either by entering the code into the address bar, or by finding an XSS vulnerability in a website. Note that the changes can only be seen by you and are not permanent.
This extension allows you to write, save, and execute javascript into web pages. You can save scripts to be run globally (on any page), on a specific domain, on a specific page, or via a "URL contains" string.
Thanks to the comments on this ticket, the solution in my case was Method 2 from this answer: https://stackoverflow.com/a/9517879
Special thanks to https://stackoverflow.com/users/3959875/woxxom
Here is a link to the finished solution:
https://github.com/nddipiazza/oogi/commit/64e1ef8dc3abfb32fec2db5fb67891a29cfe12ea
The important part of the code that makes the difference is here
var actualCode = `var cookieGetter = document.__lookupGetter__("cookie").bind(document);
var cookieSetter = document.__lookupSetter__("cookie").bind(document);
var getPrefix = function() {
return "oogi$"
};
var processCookieStr = function(cookiesStr) {
var prefix = getPrefix();
var cookieStrList = cookiesStr.split('; ');
var newStrList = [];
cookieStrList.forEach(function(cookieStr){
if (cookieStr.indexOf(prefix)==0) {
newStrList.push(cookieStr.substring(prefix.length, cookieStr.length));
}
});
return newStrList.join("; ");
};
var processSetCookieStr = function(str) {
console.log("Processing set cookie string " + str);
return getPrefix()+str;
};
Object.defineProperty(document, 'cookie', {
get: function() {
var storedCookieStr = cookieGetter();
console.log("Intercepted a cookie get " + storedCookieStr + " , and returning processed cookie string " + processCookieStr(storedCookieStr));
return processCookieStr(storedCookieStr);
},
set: function(cookieString) {
var newValue = processSetCookieStr(cookieString);
console.log("Intercepted a cookie set " + newValue)
return cookieSetter(newValue);
}
});
console.log("cookie get/set injector completed");
`;
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With