jQuery(JavaScript)でHTMLエスケープするときの注意点と対処法

jQuery(JavaScript)でHTMLエスケープするときの注意点と対処法

HTMLエスケープの注意点

昨日、このような記事がはてブに上がっていた。

innerText(textContent)/innerHTMLを使ったHTMLエスケープは充分でないので今すぐやめろ、お前たちはもう終わりだ

要約するとreturn $('<div />').text(content).html()を使用したやり方だと「"」などをエスケープしないので.replaceで置き換えたものを使いましょうという話。

ただし、元記事のコードだと`(グレイヴアクセント)の置換処理が入っていなかったので下記のように書き換えるほうが良さそうだ。

var str = '& < > ` " ' + "'";
var escapeHtml = (function (String) {
  var escapeMap = {
    '&': '&amp;',
    "'": '&#x27;',
    '`': '&#x60;',
    '"': '&quot;',
    '<': '&lt;',
    '>': '&gt;'
  };
  var escapeReg = '[';
  var reg;
  for (var p in escapeMap) {
    if (escapeMap.hasOwnProperty(p)) {
      escapeReg += p;
    }
  }
  escapeReg += ']';
  reg = new RegExp(escapeReg, 'g');

  return function escapeHtml (str) {
    str = (str === null || str === undefined) ? '' : '' + str;
    return str.replace(reg, function (match) {
      return escapeMap[match];
    });
  };
}(String));
console.log(escapeHtml(str));
// => &amp; &lt; &gt; &#x60; &quot; &#x27;

JavaScriptのHTMLエスケープサンプル

ライブラリを使用している場合

jQueryはHTMLエスケープのメソッドが存在しないがJavaScriptライブラリによってはエスケープのメソッドがあらかじめ用意されている場合がある。

Underscore.jsのHTMLエスケープ

※Underscore.js 1.6.0以下は`(グレイヴアクセント)を置換しないので注意

var str = '& < > " ` ' + "'";
str = _.escape(str);
console.log(str);
// => &amp; &lt; &gt; &quot; &#x60 &#27;

prototype.jsのHTMLエスケープ

escapeHTML()があるが& < >しかエスケープしないので使用しないほうが良い。

var str = '& < > " ` ' + "'";
console.log(str.escapeHTML());
// => &amp; &lt; &gt; " ` '

HTMLエスケープ用メソッドがないライブラリ

  • jQuery
  • AngularJS
  • Vue.jsなど

※AngularJSやVue.jsはバインディングの際にHTMLエスケープしてくれるので通常はHTMLエスケープ用メソッドは必要がない。

追記:ES6によるモダンなコードを追加

const htmlEscape = (str) => {
  if (!str) return;
  return str.replace(/[<>&"'`]/g, (match) => {
    const escape = {
      '<': '&lt;',
      '>': '&gt;',
      '&': '&amp;',
      '"': '&quot;',
      "'": '&#39;',
      '`': '&#x60;'
    };
    return escape[match];
  });
}
console.log(htmlEscape('& < > ` " ' + "'"));
// => &amp; &lt; &gt; &#x60; &quot; &#39;