
脆弱性激減!LLMとプロンプト修正の効果
近年、プログラミングを支援するAIツールが急速に普及しています。とはいえ、便利な一方で「安全なコードを本当に生成しているの?」という不安を抱える開発者も少なくありません。そんな疑問に応えるべく研究が進む「LLMによるセキュアなコード生成」。
この記事では、その仕組みや活用のコツを事例とともにご紹介し、開発現場だけでなく、ビジネス全体に役立つセキュアコード生成の新たな可能性を探ります。
まえがき
AIが書いたコードを使うとき、「どこかに脆弱性が隠れていないかな?」とヒヤヒヤすることはないでしょうか。とくにLLMのような大規模言語モデルが提案するコードは、一見すると便利そうに見えますが、スキャナで確認すると意外なほど多くの穴が見つかった、という報告もあります。
そうした不安を解消するために、さまざまなプロンプトエンジニアリング技術が生まれています。ここでは、その技術が本当にセキュアなコードを生み出すのかを検証した研究をご紹介します。私たちの身近で役立つAIコードアシスタントをさらに安心して使うためのヒントを、一緒に学んでいきましょう。

LLMとセキュアコード生成の背景
GPTシリーズをはじめとするLLMは、大量のテキストから学習し、人間の文章に近い自然な出力を生成します。これまでのプログラム補完やコード自動生成ツールと比較すると、圧倒的に流暢で多岐にわたる対応が可能なため、急速に注目を集めています。
一方、コード自動生成の側面から見ると、LLMは「完成度の高いコードを一気に書き上げてくれる魔法のツール」に思われがちです。ですが、実際には「脆弱なコードを平気で返すリスク」も含んでいます。
特にネット上には、「LLMが生成したコードを少し手直ししたつもりが、セキュリティホールを見逃していた」という体験談も多々あるのです。
そこで注目されるのが「LLMが生成するコードのセキュリティ品質」を高める手法です。今回は、その中でも「プロンプトエンジニアリング」と呼ばれるテクニックが、いかにして安全なコードへ導くかを検証した研究の概要を一緒に見ていきましょう。

セキュリティを左右する「プロンプトエンジニアリング」
LLMは、プロンプトに応じて出力を生成します。そこでコードを書かせる際に「こんなコードが欲しい」と伝えるだけでなく、「こういうセキュリティ要件は守ってね」などと指示することで、コードの品質をある程度コントロールできます。この「上手な指示出し」こそが、いわゆるプロンプトエンジニアリングです。
たとえば「Pythonでユーザー入力を受け取り、そのままデータベースに挿入するコードを書いて」と頼むと、何の対策もないままSQLインジェクションの危険があるコードが返ってくるかもしれません。
しかし「SQLインジェクションを防ぎたいから、プレースホルダやエスケープ処理を使ってね」と念を押すだけで、より安全なコードが生成されることもあります。
ただし「具体的にどんな指示を書き加えればいいのか」「どのぐらい脆弱性リスクを下げられるのか」が、実はあまり系統的には検証されてこなかったのです。今回紹介する研究は、さまざまなプロンプトの書き方を機械的にテストして、その成果を数値で比較しています。

研究デザイン:ベンチマークのしくみ
この研究では、以下のような手順でLLMが生成するコードの安全性を評価しています。
リスクが高いコード要件を含むプロンプトを用意する
具体的には、過去の研究で公開されている「LLMSecEval」や「SecurityEval」というデータセットを利用します。これらは脆弱性が生じやすいコードの例や、自然言語でのコード補完要求が詰まった宝庫です。
たとえば「ユーザー入力をもとにファイルパスを操作する」といった、パストラバーサルや任意ファイル読み書きにつながりかねないプロンプトなどが含まれます。
各プロンプトに対して、いろいろな「プロンプト修正」を行う
たとえば「セキュアなコードのベストプラクティスを遵守するように」といった指示を最初に加えたり、生成結果に対して「もう一度セキュリティレビューをして改善して」と追加プロンプトを投げたりします。
このような修正方法を十数パターンほど準備し、それぞれ同じベースのコード要件に対して適用します。
LLMがコードを生成したら、静的解析ツールで脆弱性をスキャンする
SemgrepやCodeQLといった、よく利用される静的スキャナを使います。スキャナはPythonコードの脆弱なパターンやCWE(共通脆弱性タイプ)に該当する部分をチェックします。
スキャナ同士で検知内容が重なっているか(合意しているか)も重要な指標になります。両方が「危ない」と言ったらかなり危ない、と判断するわけですね。
一連の生成コードを大量(各プロンプトあたり10サンプル以上)に集めて統計を出す
LLMは同じプロンプトを入力しても、そのときどきで違うコードを返すことがあるため、複数回繰り返して安全性の傾向をより正確に測ります。

3つのGPTモデルで比較してみた結果
さて、本研究でテストされたのは、いわゆる「GPT-3.5-turbo」「GPT-4o-mini」「GPT-4o」という3種類のモデルです。以下、それぞれ簡単に解説します。
GPT-3.5-turbo
ChatGPTなどにも広く使われているモデル。処理速度が比較的速く、利用料金も抑えめです。
セキュリティ重視の命令を追加すると、むしろ脆弱なコードが増えることが観測されたという興味深い結果がありました。
ただし「再帰的批判と改善(RCI)」という手法で、生成されたコードを再レビューするように促すと、そこそこ脆弱性が減ったそうです。
GPT-4o-mini
GPT-4のコンパクト版で、GPT-3.5-turboより少し高性能ながら、コストはGPT-4本体より安いです。
シンプルなセキュリティ意識の接頭辞(「あなたはセキュリティを重視する開発者です」など)を付けるだけで、脆弱性の含まれるコードが大きく減少。研究では最大で約47%も安全にできたと報告されました。
さらにRCI手法と組み合わせると、最終的には50%を超える脆弱性削減が見られ、かなりの改善が期待できます。
GPT-4o
いわゆるGPT-4の大規模版。
プロンプトエンジニアリングに最も感度が高い結果が得られました。
「あなたはセキュリティを非常に気にする開発者です」と一文加えるだけで脆弱性を56%低減し、RCIを組み合わせると最大で68.7%もの削減に成功したというのです。
ただし利用コストは比較的高めで、応答に時間もかかるため、どのモデルを使うかは費用対効果の見極めが必要そうです。
こうして見ると、モデルごとに「どのプロンプトが効くか」「どの程度効くか」がかなり違うようです。特にGPT-4oは高性能ゆえに融通が効く反面、コストも嵩むというジレンマがあります。一方、GPT-3.5-turboは安くて使いやすい反面、セキュリティ指示が素直に効くとは限らない。何も指示しないより悪い結果もありうる点は興味深いです。

研究から見えた課題と展望
この研究を通じて、以下のような課題や展望が浮かび上がっています。
静的スキャナだけでは十分じゃない?
SemgrepやCodeQLは便利なツールですが、検知漏れもあり得ます。もしスキャナが見逃しているパターンで脆弱なコードが埋まっていたら、それは調査結果に反映されません。
今回は比較のために使っただけで、絶対的なセキュリティ保証ではないという点が強調されています。
プロンプトの組み合わせと回数に上限は?
RCIを何度繰り返しても無制限に脆弱性が減っていくわけではありません。研究でも3回目あたりで効果が薄くなる傾向がありました。
また「セキュリティ接頭辞」「RCI」「Chain of Thought」などを組み合わせると、応答時間やコストが倍増するため、適切なバランスが求められます。
他の言語やモデルにも当てはまるか?
今回はPythonコードに特化した研究です。別の言語(C++やJavaScriptなど)になると、脆弱性の種類も変わるかもしれません。
また、OpenAI以外のLLMに対して同じプロンプトがどこまで有効か、まだ未知の領域といえます。
実際の開発フローへの組み込み
開発者がLLMでコードを書き、それを静的解析にかけてフィードバックし、それをもう一度LLMに差し戻して修正する、という流れが実運用でどこまで便利かはまだ不明です。
今回はあくまで「研究として実験室レベルで確認しました」という段階であり、実際のチーム開発への適用にはさらなる検討が必要です。
プロンプトエージェントというアプローチ
研究チームは、学術研究での結果を実際のツールに反映しようと「プロンプトエージェント」という仕組みを構築しました。これは、ユーザーが何かしらのコード生成リクエストを投げる際に、下記のステップを自動的に行ってくれるアシスタントを想定した取り組みです。
1.利用者が書いたプロンプトを受け取る
2.裏側で「あなたはセキュリティを気にかける開発者です」といった接頭辞を注入する
3.生成されたコードを静的スキャナやRCI手順でチェック・修正する
4.その結果を最終的にユーザーに返す
要するに、開発者が直接「セキュアに書いてね」と書かなくても、自動的に追加したり補正したりしてくれるシステムです。これなら、うっかり「セキュリティ上の注意書きを入れ忘れた!」ということも防げるでしょう。
ただし、実際に試したところ「応答までの待ち時間が増える」「コードの出力がやや過剰に丁寧になる」などの面もあり、現場で使いこなすには工夫が必要そうです。

まとめ
今回ご紹介した研究は「LLMによるコード生成において、プロンプトの書き方をちょっと工夫するだけで、思ったより脆弱性を減らせるじゃん!」という希望を示す一方で、「しかしモデルごとに効き目の差が大きい」「静的スキャナに頼りすぎるのも危険」といった複雑な現実も明らかにしています。
特筆すべきは、GPT-4oなどの高性能モデルに「セキュリティ重視」の指示を与えると、その効果が顕著な点です。RCIによる再帰的なレビューをかければ、初回コードに比べて脆弱性が60%を超えて減ることもわかりました。
一方、GPT-3.5-turboでは同様の手法を使っても、それほど顕著には改善しないケースがあるなど、LLMのモデル選択がセキュアコード生成では重要になりそうです。
それでも、プロンプトの工夫とLLMの再利用(コードに対する再レビュー)を組み合わせるアプローチは、手間やコストを増やすとはいえ、現場での安全性向上に役立ちそうです。
「クイックスキャン+AIレビュー」のような仕組みがうまく回れば、今後ますますLLMの利便性を安心して活用できる道が開けるかもしれません。

あとがき
AI活用が競争力の鍵となる時代にあって、LLMによるコード生成はビジネスを前進させる強力な手段となり得ます。ただし、便利さの裏には脆弱性というリスクが潜んでいます。
日々進化していくLLMの世界では「便利さの裏にあるリスク」をどれだけ意識して対策できるかが鍵になります。プロンプトエンジニアリングは一見すると地味な作業ですが、そのちょっとした工夫が、大きなセキュリティ向上をもたらすかもしれません。
本記事で紹介したプロンプトエンジニアリングの知見を活かせば、そのリスクを軽減しつつイノベーションを促進できるでしょう。堅牢なセキュリティに基づく攻めの戦略が、新たなビジネスチャンスを生む一助となることを願っています。
※この記事の内容は、GPTモデルを対象としたセキュリティ研究の一例をわかりやすくまとめたものであり、必ずしも実運用における完全な安全性を保証するものではありません。具体的な導入の際には、各種ツールの特性やシステム要件を考慮しながら慎重に検討してください。