普段はサーバーサイドですが、フロントエンドの仕事も少し増えたので、Javascript勉強中にevalすごく便利!と思ったら、とてもリスクがあることを知ったので、メモとして残しておこうと思いました。
もうすでにネット上でたくさん情報は転がっているので、当たり前じゃん!というツッコミもあるかと思いますが。。。
やりたかったこと
以下のような仕組みを実装しようと試みました。
- 動的にObjectのキーと値を生成する。
- 生成したObjectにキーを指定して、値を取得する。
ダメな例
実証例のため、はちゃめちゃなコードですが、ご了承を。。。
ng.html
<body>
名前:<input type="text" id="name" value="NG NAME"></input>
年齢:<input type="text" id="age" value="NG AGE"></input>
<input type="button" id="btn" value="送信"></input>
<div id="output"></div>
<script>
window.addEventListener('DOMContentLoaded',function(){
function init(){
const ids = ['name', 'age'];
const MyObj = {};
// ids配列の値をidとして、各要素を取得。
// idをMyObjのキーとして、要素の値を設定する。
for(let i = 0, ilen = ids.length; i < ilen; i++){
const elm = document.getElementById(ids[i]);
eval('MyObj.'+ids[i]+'="'+elm.value+'";');
document.getElementById('output').textContent += eval('MyObj.'+ids[i]);
}
const btn = document.getElementById('btn');
btn.addEventListener('click', init, false);
}
init();
});
</script>
</body>
初期表示時点ではこのような感じ。
下記のように入力して、送信。
これで任意のコードが実行できてしまう。。。
解決策
ブラケット構文を使用しましょう!
ok.html
for(let i = 0, ilen = ids.length; i < ilen; i++){
const elm = document.getElementById(ids[i]);
MyObj[ids[i]] = elm.value;
document.getElementById('output').textContent += MyObj[ids[i]];
}
変数に入っている値をキーとして使用できるのは、とても便利ですね。
evalはパフォーマンスにも影響があるそうなので、上記のリスクも踏まえるとevalを使用するのはなるべく避けた方がよさそうです!