evalとFunctionを使わず文字列をJSコードとして実行する

以下のコードは古のスーパーハカーが書いたと言われる、SNSでシェアしただけで行政機関の執行を受けるほどの危険なコードらしい。

for(;;) alert('何回閉じても無駄ですよ~');

なぜこのコードが危険なのか私には説明できないのだが、そんなコードを実行可能なスクリプトのまま扱うのは良くない。文字列にしてしまおう。

const src = "for(;;) alert('何回閉じても無駄ですよ~')";

とりあえずこれで安心と言いたいところだが、ご存知のようにJavaScriptにはevalやFunctionという文字列をスクリプトとして動的に実行する仕組みがある。

eval(src);

(Function(src))();

実はこれ以外にも文字列を実行できる第3の方法がある。文字列をObject URLまたはData URIに変換し、これを動的生成したscript要素のsrcにセットして、DOMツリーに追加するという方法だ。

Object URLの場合

const src = "for(;;) alert('何回閉じても無駄ですよ~')";
const objURL = URL.createObjectURL(new Blob([src], {type: 'application/javascript'}));

const s = document.createElement('script');
s.src = objURL;
document.querySelector("head").appendChild(s);

Data URIの場合

const src = "for(;;) alert('何回閉じても無駄ですよ~')";
const fr = new FileReader();
fr.onload = (e) => {
    const dataURI = e.target.result;
    const s = document.createElement('script');
    s.src = dataURI;
    document.querySelector("head").appendChild(s);
};
fr.readAsDataURL(new Blob([src], {type: 'application/javascript'}));