I need to make sure that some specific native Javascript functions are not patched nor overrode.
Unfortunately, I cannot do that with accessing the .toString()
of the function or Function.prototype.toString
with one of bind apply or call, since the Function.prototype.toString
is one of the functions I have to test.
Is there any other method which returns the value (the function itself) of a function? (Or [Native Code]
for native JS functions)
Editing: One of the purposes of this test is to check if the client is a bot that patches some JS functions. Creating new frame and taking its Function.prototype.toString
value won't work in that case
In response to edit
If it's a malicious client that can't or won't update their bot script in response to your checks, then just save a copy of Function.prototype.toString()
using javascript in your HTML header to a temp variable. Then check against this to see if the client has mutated the js at all.
If the client is malicious AND is trying to actively avoid your checks by changing their bot, then there is simply no iron-clad way to stop them. It will become an arms-race where you patch in checks and they patch in fixes in response. Ultimately, the client has the final say in what gets run in their browser, so you might want to think again about why you're doing these checks to see if there's another viable approach to your problem.
Initial Answer
You could re-request the whole .js file and parse it all as a string. You would have to do this for every js file and find a good pattern for determining if your functions have been over-written, so it may not work for your needs.
// my JS file is being served from giorgiosjames.com/myjs.js
const myJs = await fetch('giorgiosjames.com/myjs.js').then(res => res.text());
// parse myJs here, something like
if (myJs.includes('Function.prototype.toString = ')) // do something
If you can constrain your use to the latest Firefox, you can use the method .toSource()
, but no other browsers support it and it is not standard. More reading here
// only in latest Firefox
const x = () => 'wow';
console.log(x.toSource())
// returns "() => 'wow'"
And as a frame challenge, you could probably still be using the (arguably) best approach of Function.prototype.toString
by:
First checking if toString works.
Resetting .toString()
if it has been overridden.
.toString()
.toString()
if necessarylet temp = null;
if (Function.prototype.toString.toString() !== 'function toString() { [native code] }') {
// save overridden function if you need to come back to it
temp = Function.prototype.toString;
// getting the original toString function by creating an iframe
const iframe = docuemnt.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe);
Function.prototype.toString = iframe.contentWindow.Function.prototype.toString;
}
// do your other checks here ex//
if (Array.prototype.includes.toString() !== iframe.contentWindow.Array.prototype.includes.toString()) {
// do something
}
// ..or however you're planning on checking for overridden functions
// restore toString from temp if needed.
Function.prototype.toString = temp;
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