そのeval()、まだ使っているのか?――動的コード実行が招く地獄と現代的な回避策
現場でコードレビューをしていると、今でもたまに遭遇するんだ。「これ、動的に関数を呼び出したいからeval()使っちゃいました」というコードに。
結論から言うと、eval()やsetTimeout()への文字列渡しは、セキュリティの文脈では「核兵器の起爆スイッチを外部公開する」のと同義だ。
今回は、なぜこれらが悪魔の所業なのか、そしてモダンな開発現場でどう代替すべきかを、実務的な視点で叩き込んでおく。
—
1. なぜeval()は「死」を招くのか
eval()は、引数に渡された文字列を「その場のJavaScriptコード」として解釈・実行する。もし、その文字列の中にユーザーが入力したデータが混入していたらどうなるか?
攻撃者は、あなたのアプリケーションのコンテキスト(セッション情報やCookie、DOM)を自由自在に操れるようになる。
攻撃のPoC(概念実証)
例えば、ユーザーのプロフィール表示機能でこんな実装があったとしよう。
// 危険な実装例
const userInput = new URLSearchParams(window.location.search).get(“name”);
eval(“console.log(‘Hello, ” + userInput + “‘);”);
攻撃者が以下のURLを送りつけるだけで、XSS(クロスサイトスクリプティング)が成立する。
?name='); alert(document.cookie); //
ブラウザはこれを以下のコードとして解釈する。
console.log('Hello, '); alert(document.cookie); //');
これで君のアプリのセッションハイジャックは完了だ。setTimeout()やsetInterval()も同様に、第一引数に文字列を渡すと内部でeval()相当の処理が走る。これは言語仕様上の「負の遺産」と言ってもいい。
—
2. 脱eval():現代的な代替実装
「動的に処理を切り替えたい」というニーズは理解できる。だが、文字列でコードを組み立てる必要はない。「マップ(連想配列)」を使えばいいんだ。
安全な実装サンプル(JavaScript)
// 悪用を許さない、安全なコマンド実行パターン
const commandMap = {
“greet”: () => console.log(“Hello!”),
“farewell”: () => console.log(“Goodbye!”),
“error”: () => console.error(“Unknown command”)
};
const userInput = “greet”; // ユーザーからの入力値
// 文字列を直接実行せず、プロパティとして参照する
const action = commandMap[userInput] || commandMap[“error”];
action();
これなら、存在しないキーが指定されても関数が実行されることはない。これが、境界防御の基本だ。
—
3. インフラレベルでの防御:CSP(Content Security Policy)
コードレベルで完璧を期すのは当然だが、万が一の脆弱性混入に備えて、CSPでトドメを刺しておくべきだ。
CSPの script-src ディレクティブで unsafe-eval を許可しなければ、たとえコード内にeval()が残っていても、ブラウザは実行を拒否する。
NginxでのCSP設定例
HTTPレスポンスヘッダーにセキュリティポリシーを注入
add_header Content-Security-Policy “default-src ‘self’; script-src ‘self’; object-src ‘none’;”;
script-src 'self': 自分のドメインのスクリプトしか実行させない。'unsafe-eval'を記述しない : これだけで、eval()やnew Function()の使用はブラウザ側でブロックされる。
—
4. 最後に:エンジニアとしての矜持
「動的に処理を書きたい」という欲求は、プログラマーの怠慢(良い意味での)から生まれることが多い。だが、その怠慢がセキュリティホールを生むなら、それはプロとして失格だ。
1. 文字列をコードとして解釈させるな。
2. 実行したい処理は、事前に定義したオブジェクトのキーにマッピングせよ。
3. CSPを導入し、ブラウザに「疑わしいコードは動かすな」と命令せよ。
これらは教科書的な知識じゃない。現場で数々のインシデントを見てきた人間が辿り着く、最低限の「防弾チョッキ」だ。
もし君のプロジェクトでeval()を見かけたら、即座にリファクタリングのチケットを切ってくれ。それが、君のシステムとユーザーを守るための、最も手っ取り早くて確実な投資になる。
コメント