【入門編】JavaScriptのeval()およびsetTimeout()への文字列渡しによるリスク – アプリケーションセキュリティ & 安全な開発防御ガイド

「何でも実行しちゃう魔法の箱」の落とし穴:eval()とsetTimeout()の危険性

こんにちは。セキュリティの世界へようこそ。
日々、コードを書いていると「ユーザーが入力した文字を、そのままプログラムとして動かせたら便利なのにな」と思うことはありませんか?

実は、そんな時に使われる eval() や、時間の遅延処理で使われる setTimeout() の「文字列渡し」という機能は、セキュリティの現場では「泥棒に家の合鍵を渡すようなもの」と言われるほど危険なものなんです。

今日は、なぜこれらが危険なのか、そしてどうやって身を守ればいいのか、泥棒の侵入経路に例えて一緒に見ていきましょう。

—

1. なぜ「eval()」がそんなに危ないのか?

eval() という関数は、中身に書かれた文字列を「プログラムの命令」としてそのまま実行してしまいます。

例えば、家の中に「手紙に書かれた命令を何でも聞くロボット」がいると想像してください。あなたが「電気を消して」と書けば電気を消してくれます。でも、もし悪い泥棒が勝手に家に入り込んで、「金庫を開けて、中身を外に投げ捨てろ」という手紙をロボットに渡したらどうなるでしょう?

ロボットは善悪の判断をせず、ただ命令を実行します。これが eval() の正体です。

// 危険な例:ユーザーからの入力をそのまま実行してしまう
let userInput = “alert(‘ハッキング成功!’)”; // 本当はもっと悪質なコードが来るかも…
eval(userInput);

このように、誰が書いたかわからない文字列を eval() に放り込むことは、「家のドアを全開にして、誰でも入れるようにしている」のと同じことなんです。

—

2. 実は盲点?「setTimeout()」に潜む罠

「えっ、setTimeout() は時間を待つだけの関数でしょ?」と思いましたか?
実は、setTimeout() にも「文字列」を渡せてしまうという、昔ながらの仕様が残っています。

// 危険な例:文字列を渡すと、内部でeval()と同じことが起こる
setTimeout(“console.log(‘こんにちは!’)”, 1000);

この記法を使うと、ブラウザは「ああ、この文字列を実行すればいいんだね」と判断し、内部で eval() と同じ処理を行います。知らず知らずのうちに、自分のプログラムの中に「泥棒専用の入り口」を作ってしまっている可能性があるのです。

—

3. 防御の基本:どうやって泥棒を追い出すか?

では、どうすれば安全に開発できるのでしょうか。対策は「文字列を渡さないこと」に尽きます。

対策A:文字列ではなく「関数」を渡す

setTimeout() を使うときは、文字列ではなく、あらかじめ定義した関数を渡すようにしましょう。これなら、泥棒が手紙をすり替える余地はありません。

// 安全な例:関数を直接渡す
setTimeout(() => {
console.log(‘これなら安全です!’);
}, 1000);

対策B:CSP(コンテンツセキュリティポリシー)で門番を置く

もし万が一、コードの中に危険な記述があったとしても、最終的な防波堤として CSP(Content Security Policy) という設定を導入しましょう。

これは、Webサイトが「どの場所から読み込んだプログラムなら実行していいか」を定義する、家を守る最強の警備員のような仕組みです。

HTMLのヘッダーに以下のように設定することで、「eval() やインラインのスクリプトは禁止!」とブラウザに指示を出せます。

HTTPレスポンスヘッダーの例
Content-Security-Policy: default-src ‘self’; script-src ‘self’;

※ script-src 'self' とすることで、自分のサーバー外からの怪しいコードや、eval() の実行をブラウザ側でブロックできます。

—

最後に:一歩ずつ、安全な開発者へ

セキュリティと聞くと、「難しそう」「今のコードを全部書き直すの?」と不安になるかもしれません。でも、まずは今日学んだ「eval() には文字列を渡さない」「setTimeout() には関数を渡す」という小さなルールを守るだけで、あなたのプログラムは格段に強くなります。

セキュリティは、一度にすべてを完璧にする必要はありません。泥棒が入れないように「鍵をかける」「窓を閉める」といった、小さな積み重ねが、あなた自身とユーザーのデータを守ることに繋がります。

一歩ずつ、一緒に学んでいきましょう!何か不明な点があれば、いつでも質問してくださいね。応援しています。

コメント

タイトルとURLをコピーしました