JavaScript makes it easy to overwrite properties and functions of the global object. I'd like to find a way to check if the original version of a global property has been replaced.
Consider someone putting this in their HTML:
<script type="text/javascript">
window.encodeURIComponent = eval;
</script>
<script type="text/javascript" src="myscript.js"></script>
If myscript.js calls the encodeURIComponent function somewhere, it will now behave unpredictably. So is there a way I can check inside myscript.js if someone has overwritten that function before I use it?
JavaScript makes it easy to overwrite properties and functions of the global object. I'd like to find a way to check if the original version of a global property has been replaced.
Consider someone putting this in their HTML:
<script type="text/javascript">
window.encodeURIComponent = eval;
</script>
<script type="text/javascript" src="myscript.js"></script>
If myscript.js calls the encodeURIComponent function somewhere, it will now behave unpredictably. So is there a way I can check inside myscript.js if someone has overwritten that function before I use it?
Share Improve this question asked Apr 22, 2012 at 7:33 GOTO 0GOTO 0 47.8k25 gold badges138 silver badges164 bronze badges 05 Answers
Reset to default 7The only thing I know is a straightforward approach with analysis of string representation of the function. Normally, the code
window.encodeURIComponent.toString()
should produce something like this:
function encodeURIComponent() { [native code] }
which can be easily parsed for key info function encodeURIComponent
.
If the function was overwritten by eval
, as in your example, you'll get:
function eval() { [native code] }
In general, for checking window
properties, you can create a fake iframe and pare window.[property].toString()
with iframe.contentWindow.[property].toString()
. If the parison gives false
, the property has been changed.
One interesting way to do this inside one script is to pare function prototype
By default - typeof window.encodeURIComponent.prototype === "undefined"
But if someone redefines this function by
window.encodeURIComponent = function() { eval(); }
we will get
typeof window.encodeURIComponent.prototype === "Object"
PS: this method is more reliable then others, but it won't give you 100% gurante. JavaScript is all objects and all in runtime.. just live with this..
UPDATE you can bine both methods.. mine and @Stans..
this example don't work because I wasn't using eval
- eval Is also having prototype "undefined" by default.. so you can do this
window.encodeURIComponent.name === "encodeURIComponent"
//to make shure that user won't use EVAL
&& typeof window.encodeURIComponent.prototype === "undefined"
//to make shure that user won't use self defined function
This is browser specific and definitely will not work for non-functions, but:
Calling a function's toString
method should produce something like:
Chrome:
"function encodeURIComponent() { [native code] }"
Firefox:
"function encodeURIComponent() {
[native code]
}"
IE 7/8/9:
"
function encodeURIComponent() {
[native code]
}
"
Observe that the function's name matches the property's name, and its body is replaced by "[native code]
". The idea is to remove all whitespace from this string and pare it to the expected result, "functionxxx(){[nativecode]}"
.
I have no idea if it works for all browsers/functions, that's trial and error:
var pattern = 'function' + propertyName + '(){[nativecode]}';
var func = window[propertyName].toString();
if(func.replace(/\s+/g, '') !== pattern) {
throw new Error("Property window." + propertyName + " has been modified!");
}
How about this?
function isNativeWindowProperty(propertyName) {
var result = false;
var iframe = document.createElement('iframe');
iframe.src = 'javascript:;';
document.getElementsByTagName('body')[0].appendChild(iframe);
if (window[propertyName].toString() === iframe.contentWindow[propertyName].toString()) {
// check window[propertyName].toString override
if (window[propertyName].toString.toString() === iframe.contentWindow[propertyName].toString.toString()) {
result = true;
}
}
iframe.parentNode.removeChild(iframe);
return result;
};
console.log(isNativeWindowProperty('alert')); // true
window.alert = function() {};
console.log(isNativeWindowProperty('alert')); // false
window.alert.toString = function() {
return 'function alert() { [native code] }';
};
console.log(isNativeWindowProperty('alert')); // false
There is an EASY way to do it in JavaScript :) But you have to have access to the HTML, so you can't use this method inside of one script..
function is an OBJECT.. so we can save a link to an object and just pare those links. Just think of a function like it a simple object. How can you pare objects?
<script type="text/javascript">
var a = window.encodeURIComponent; // a === window.encodeURIComponent -> true
</script>
<script type="text/javascript">
window.encodeURIComponent = eval; // a === window.encodeURIComponent -> false
</script>
<script type="text/javascript" src="myscript.js">
if (a !== window.encodeURIComponent)
{
throw new Error('Someone redefined function');
}
</script>