Triynko
Triynko

Reputation: 19204

Native JavaScript support for HTML attribute encoding and JavaScript string encoding?

Attribute values need to be encoded. If I'm building a jQuery object like so:

$('<div data-value="' + value + '">');

Really, value must be attribute encoded like so:

$('<div data-value="' + HtmlAttributeEncode(value) + '">');

I cannot find such a native function. Some suggest it's simply a matter of replacing double quotes with &quot;, but Microsoft's HttpEncoder.HtmlAttributeEncode method encodes these four characters & < " '. I've seem implementations such as quoteattr here: https://stackoverflow.com/a/9756789/88409, but that is horribly inefficient, calling replace to iterate over the string multiple times. Likewise, I need a native function for encoding a javascript string (e.g. $('<div onclick="var s =\'' + HtmlAttributeEncode(JavaScriptStringEncode(value)) + '\';alert(s);"></div>).appendTo(body); << contrived example for illustration only)

Is there a native equivalent of this functionality?

Note: Please don't mention escape (which is now deprecated in favor of encodeURI and encodeURIComponent) all of which have nothing to do with attribute encoding.

Upvotes: 7

Views: 5517

Answers (4)

seanf
seanf

Reputation: 6734

Here is a vanilla JS version (no jQuery), inspired mostly by Garr Godfrey's answer, based mostly on Quentin's answer. It should handle browsers which choose to wrap attributes in single quotes for whatever reason. Use at your own risk, etc etc.

// Implementation:
/**
 * Encodes an HTML attribute using the browser's DOM methods
 */
function encodeAttr(text) {
  const elem = document.createElement('p');
  elem.setAttribute('title', text);
  const elemHtml = elem.outerHTML; // <p title="encodedText"> or maybe <p title='encodedText'>
  // Find out whether the browser used single or double quotes before encodedText
  const quote = elemHtml[elemHtml.search(/['"]/)];
  // Split up the generated HTML using the quote character; take item 1
  return elemHtml.split(new RegExp(quote))[1];
}

// Demo:
const untrustedAttribute = '"><iframe src="javascript:alert(\'XSS\');">.jpg';
document.getElementById('results').innerHTML = 
  `<span title="${encodeAttr(untrustedAttribute)}"> My content </span>`;

https://jsfiddle.net/sys2061/vorm8Ldp/16/

Upvotes: 1

Geoduck
Geoduck

Reputation: 9001

This is quite an old question, but I think more interesting with the javascript templating capabilities:

html = `<table title="${ myTitleVar }"><thead><tr>
</tr></thead></table>`

No longer is this error prone and stringing together hundreds of jquery functions is just impractical and unportable.

So, there is a little trick for encoding attributes. Should work fine. I want to make sure i don't have quotes or some nonsense in myTitleVar, so:

    var $h=$('<span>');
    function encodeAttr(t) {
        return $h.attr('title',t).prop('outerHTML').match(/title="(.*)"/)[1];
    }

    html = `<table title="${ encodeAttr(myTitleVar) }"><thead><tr>
       </tr></thead></table>`


I haven't tested in all browsers. It's possible some generate the html using ' instead of ", which would make it a little more challenging.

https://jsfiddle.net/p359ux01/

Upvotes: 2

Rannie Aguilar Peralta
Rannie Aguilar Peralta

Reputation: 1742

Found an npm package that will get your job done!

https://www.npmjs.com/package/escape-html

Upvotes: -2

Quentin
Quentin

Reputation: 943635

No.

But you don't need them since you can build elements using DOM methods (or jQuery's wrappers around them) which bypass the need for escaping since you are dealing with a DOM instead of HTML.

$('<div />', { "data-value" : value });

or

var div = document.createElement('div');
div.setAttribute('data-value', value);

If you really want to get the escaped HTML, you can take a DOM and generate HTML from it:

var html = $('<div />').append(
    $('<div />', { "data-value" : value })
).html();

Upvotes: 3

Related Questions