How to convert anything to a String safely in JavaScript
One option is:
Object.prototype.toString.call(test)
This gives:
"[object Object]"
in the case of test. Basically, it just gives type information. However, I wonder what the exact scenario is here. How is the evil object getting loaded into the page? If they can execute arbitrary code on the page, you're basically out of luck. Among other things, it is then possible to redefine Object.prototype.toString
.
JavaScript allows you to modify the properties of pretty much any object that is accessible to your script, including Object.prototype
itself, meaning any object is vulnerable to "evil code" in the manner that you explained.
Only primitives are guaranteed to be safe, so the only way to ensure that "evil code" is never executed is to do something like this:
function safeToString(x) {
switch (typeof x) {
case 'object':
return 'object';
case 'function':
return 'function';
default:
return x + '';
}
}
Sadly, @Matthew Flaschen's (currently accepted) answer does not work with the Symbol
class from ES6 / ES2015:
console.log("" + Symbol("foo"));
// results in an exception:
// `Uncaught TypeError: Cannot convert a Symbol value to a string`
// (at least in Chrome as of this writing).
https://jsfiddle.net/L8adq9y4/
(I have no idea why, as Symbol
has a perfectly good toString()
method:)
console.log(Symbol("foo").toString());
https://jsfiddle.net/v1rqfhru/
There's a solution though: the String()
function seems to be able to convert any value (at least out of the ones I tried) into a String
. It will even call toString()
if it exists:
console.log(String("A String"));
console.log(String(undefined));
console.log(String(null));
console.log(String({value: "An arbitrary object"}));
console.log(String({toString: function(){return "An object with a toString() method";}}));
console.log(String(function(){return "An arbitrary function"}));
https://jsfiddle.net/6uc83tsc/
So, pass anything you like into String()
and you'll get a pretty good result.