Simple function to generate an HTML-safe string Sometimes, we have to do some fixing to insert a string into an HTML property. Or just to display it.

But not everything is safe! Consider the following example:


document.getElementById('name').innerHTML = prompt('What is your name?');



This allows to introduce HTML vulnerabilities quite easily. Specially when you want to do HTML > X/HTML conversions.

So, I've came up with the following:

var safetext = function(text){
    var div = document.createElement('div');
    div.innerText = div.textContent = text;
    var safetext = div.innerHTML;
    div = null;
    return safetext.replace(/^\s+|\s+$/g, '');
};


But then I realized that it could be optimized a little. That div is created and destroyed every single time you need a cleanup. So, I've optimized to the following:

var safetext = (function(text){
    this.innerText = this.textContent = text;
    return this.innerHTML.replace(/^\s+|\s+$/g, '');
}).bind(document.createElement('div'));


The this will always be the div we created, and will always be the same one, so, no unnecessary cleanups or anything. It is always kept in memory, since it is bound to the this in the anonymous function. Or isn't it?

The resulting text is a string that is safe to use in your HTML. Using the example from before:


document.getElementById('name').innerHTML = safetext(prompt('What is your name?'));



This should show &amp;lt;script&amp;gt; if your name (for some bizarre reason) is &lt;script&gt;. Or it leaves unsafe characters behind, bound to break everything?



To the best of my knowledge, and based on the 200 tests where I've used it, I didn't had a single problem or hiccup.

Am I missing something? Is my code indeed returning safe HTML strings? Is the 2nd iteration really more performant?
The Attack
What you are basically talking about is DOM based XSS.
But it's a self-XSS, so the only possible attack vector might be via ClickJacking (depending on the used browser).
Still, it should be defended against, especially for usability reasons.
Proper Defense
Here is OWASPs guide on preventing DOM based XSS. Basically, you should first HTML encode the input, and then JavaScript encode.
For your example, the second part doesn't seem necessary, just encoding &lt;, &gt;, ' and &quot; should be enough.
Your Defense
Well, your defense works.
It could be simplified a bit though. There really doesn't seem to be a need to set this.textContent, and I also do not see the need for replace(/^\s+|\s+$/g, '') (or am I missing something here? Browser compatibility maybe?).
That would leave you with
var safetext = (function(text){
    this.textContent = text;
    return this.innerHTML;
}).bind(document.createElement('div'));

The reason this works seems to be the way textContent works.
But this really seems to be more of a side-effect, and it is never a good idea to use those for security related things.
Conclusion
Regarding performance, security, and readability, a simple replace for &lt;, &gt;, ' and &quot; with their HTML representation seems to be preferable to your method.