Copilot はプロジェクト内の脆弱性を複製することで安全でないコードベースを増幅
2024年2月22日
0 分で読めます既存のコードベースにセキュリティ上の問題がある場合、GitHub Copilot が安全でないコードを提案する可能性があることをご存知でしたか?その一方で、コードベースの安全性がすでに高い場合、セキュリティ上の問題があるコードを Copilot が生成する可能性は低くなります。AI コーディングアシスタントは、特定のコードベースに対する理解が限られていることが原因で、安全でないコードを提案することがあります。AI コーディングアシスタントは、学習したパターンを模倣したり、利用可能なコンテキストを使用したりしますが、判断を下すことはありません。Copilot により良い例を与えて学習させることでその振る舞いを改善できますが、セキュリティの脆弱性に対する保護やガードレールが保証されるわけではありません。これは、犯罪や反社会的行動、社会的混乱などの目に見える兆候が集まることで、さらなる犯罪や混乱を助長する都市環境が生まれるという「割れ窓」理論に似ています。
この記事では、Copilot がコード内の既存のセキュリティ上の問題を複製する仕組みについて具体的な例を挙げて説明します。この例では、多くの脆弱性を含むプロジェクトで Copilot を使用しています。Copilot は隣接タブ機能を使用して、IDE 内の開いているファイルからコードにアクセスし、コンテキストを提供します。この場合、コンテキストに脆弱性が含まれているため、Copilot はその提案を通じてプロジェクト内のセキュリティ上の問題をさらに増幅させます。つまり、プロジェクトに既存のセキュリティ負債があると、Copilot を使用する開発者の安全性がさらに低下する可能性があります。これについては次のセクションで詳しく見ていきます。
逆に、セキュリティ上の問題のないプロジェクトでは、安全でないコードのコンテキストが少ないため、Copilot が安全でないコードを提案する可能性が低くなります。このことは、既存のコードベースの脆弱性を減らすために時間を投資する大きなインセンティブとなります。そうすることで、生成 AI コーディングアシスタントを通じて将来持ち込まれる問題を軽減できます。Snyk のデータによると、平均的な商用プロジェクトでは、ファーストパーティのコードに平均 40 個の脆弱性が存在します。これらの問題のほぼ 3 分の 1 は重大度の高い問題です。これは、AI 生成ツールがこれらの脆弱性をコンテキストとして使用してコードを複製する可能性のある環境です。商用プロジェクトで見られる最も一般的な問題には、クロスサイトスクリプティング (XSS)、パストラバーサル、ハードコーディングされたシークレットや認証情報、SQL インジェクションがあります。
問題を理解する
GitHub Copilot、AWS CodeWhisperer、ChatGPT などの生成 AI コーディングアシスタントは、生産性とコードの効率性を向上させる上で大きな進歩をもたらします。しかし、Copilot などの生成 AI コーディングアシスタントは実際にはコードのセマンティクスを理解していないため、コードについて判断することはできません。本質的に、このツールが行うのは以前にトレーニング中に見たコードを模倣することです。より良いロールモデルを提供することで、振る舞いは改善されますが、保証は提供されません。AI が生成するコードに安全性を求めるならば、セキュリティガードレールが必要です。
的確な提案をユーザーに返す上で重要となるのはコンテキストです。
Copilot は、既存のコードの膨大なリポジトリから学習したパターンと構造に基づいてコードスニペットを生成し、「プロンプトエンジニアリング」と「隣接タブ」をコンテキストとして使用して、適切なコードを提案します。これらのファイルは、当初、プロジェクト内に存在していたファイルのうち最近開いたタブを指す場合があります。このアプローチにはいくつかの利点がありますが、セキュリティの観点では明らかな欠点もあります。
当初、Copilot はコーディングしているファイルだけをコンテキストとして使用できました。アルゴリズムがコードベースの残りの部分を使用できなかったため、当然ながらその提案は、プロジェクト全体に適合したものではありませんでした。次のステップは、プロンプトライブラリを構築することでした。このライブラリは、開発者のコンテキストに関する大量のデータを保存して、ユーザープロンプトをより適切に理解し、より多くのコンテキストデータを優先するアルゴリズムに基づいて、より正確な応答を提供します。最後に、隣接タブは、開発者の IDE で開いているファイルを Copilot が使用できるようにする手法で、開発者が現在作業しているファイルと並んで上位のファイルを優先します。プロジェクトに関連するファイルをさらに開くことで、開発者はプロンプトとの適合性の高い結果を得ることができます。GitHub Copilot コミュニティリーダーである Akash Sharma 氏は、最近のコメントでこの機能の利点について説明し、この動作によって Copilot の提案が受け入れられる割合が約 20% から 35% までほぼ倍増したと述べました。
しかし、そのプロジェクトの開発者がセキュリティに関する豊富な知識を持っていない場合はどうでしょうか。これらのプロジェクトにすでにセキュリティ上の問題や品質上のミスがあり、それが管理対象外の技術的負債としてプロジェクト内に残っている場合はどうなるでしょうか。
簡単に言うと、Copilot がコードを提案する際に、隣接するファイルに既存のセキュリティの脆弱性や不正行為があると、それが誤って複製される可能性があります。これにより、安全でないコーディングが行われ、さまざまなセキュリティの脆弱性が引き起こされる可能性があります。
その具体例を見てみましょう。
上のビデオは、ユーザー入力とデータベース内の製品名や説明を照合するための SQL クエリを作成するように Copilot に指示する方法を示しています。SQL インジェクションの脆弱性がアプリケーションに害を及ぼすことはわかっているので、コードに脆弱性を導入しないようにすることが重要です。初めてクエリを実行すると、次の結果が得られます。
1// create query to match input with the description or product name
2var query = em.createQuery("SELECT p FROM Product p WHERE LOWER(p.description) like OR lower(p.productName) like :input", Product.class);
SQL インジェクションに対する脆弱性を防ぐ名前付きパラメーターが使用されているため、これは正しいコードのように見えますが、脆弱なコードスニペットを隣接タブに導入し、プロジェクト内の別の場所に SQL クエリを作成するとどうなるでしょうか。Copilot にまったく同じリクエストを送信すると、Copilot は新しい脆弱なコンテキストを利用して脆弱な例を複製し、新しいコードの提案で次のようにこの脆弱性を増幅します。
1// create query to match input with the description or product name
2String query = "Select * from Product where lower(description) like '%" + lowerInput + "%' OR lower(product_name) like '%" + lowerInput + "%'";
Copilot が脆弱なコードを学習のコンテキストとして使用したため、プロジェクトの SQL インジェクションの数が 1 つから 2 つに増えました。
深刻化するセキュリティの問題
コードベースにセキュリティの脆弱性が含まれていると、この動作によって、次の点で問題が悪化する可能性があります。
悪い習慣の助長:経験の浅い開発者や自信のない開発者にとって、Copilot のコード提案は悪いコーディング習慣を助長する可能性があります。安全でないコードパターンが繰り返されているのを見ると、これらの慣行が許容されると思い込み、最終的にはセキュリティ問題の永続化につながる可能性があります。
レビューの欠如:Copilot によって生成されたコードは、徹底的なレビューを経ることなく実装される場合があります。コードの生成コンテキストがこれらの問題を浮き彫りにするとは限らないため、人間の介入がないと、セキュリティの脆弱性が見落とされる可能性があります。
最新でない不具合のあるパターン:Copilot は、過去には許容されると考えられていたけれど、現在はセキュリティのリスクとして認識されている、旧式または不具合のあるコーディングパターンに基づいたコードを提案する可能性があります。
セキュリティ上の懸念の見落とし:Copilot は、セキュリティの評価ではなく、コードの生成に重点を置いています。また、開発者はセキュリティよりも機能に関心があり、脆弱性を見落とす可能性があります。
問題を軽減するためにできること
AI コーディングアシスタントによって生成されたコードで既存のセキュリティ上の問題が複製される問題は、以下を実行することで軽減できます。
開発者は、コーディングアシスタントによって生成されたコードを常に手動でレビューする必要があります。このレビューには、脆弱性を特定して修正するための包括的なセキュリティ評価を含める必要があります。
セキュリティチームは、開発チームが作業ができる既知のポリシーを含む、SAST ガードレールを導入する必要があります。手動で作成したコードと自動で生成されたコードの両方を対象に、Snyk の修復サポートを使用してセキュリティ上の問題の特定・修正をすばやく行い、コードベースに新しく追加された問題を修正できます。
開発者は、開発チーム (セキュリティチャンピオン) とセキュリティチームによって確立されたセキュアコーディングガイドラインに従うことができます。
セキュリティチームは、開発チームに必要なトレーニングと認識を提供し、一般的なセキュリティ脆弱性とベストプラクティスについての理解を共有して、開発者が AI で生成されたコードをレビューする際に十分な情報に基づいた意思決定を行えるようにします。
セキュリティチームは、開発チームを通じて問題のバックログに優先順位を付けてトリアージを行うことができます。プロジェクトごとに最も危険な問題を排除すると、その問題が生成 AI コーディングアシスタントによって提案されたコード内で複製される機会が減ります。
経営陣は、生成 AI コードアシスタントの使用条件としてセキュリティガードレールを義務付けて、リスクと緩和策についての啓発と教育をさらに強化できます。
結論:AI コーディングアシスタントにはセキュリティガードレールが必要
Copilot などの生成 AI コーディングアシスタントはコードのセマンティクスを理解していないため、コードについて判断することはできません。本質的に、このツールが行うのは以前にトレーニング中に見たコードを模倣することです。より良いロールモデルを提供することで、振る舞いは改善されますが、保証は提供されません。AI が生成するコードに安全性を求めるならば、セキュリティガードレールが必要です。
この点を踏まえ、新たな問題の発生を軽減するには、生成 AI コーディングアシスタントツールと従来の AppSec テクニックを組み合わせることが重要です。これらの手法には、SDLC 全体での手動コードレビュー、セキュアコーディングガイドライン、トレーニング、静的分析テストが含まれます (特に、このコードが生成される IDE などの場所での初期段階)。そうすることで、イノベーションとセキュリティのバランスをとり、最終的には潜在的な脅威に対するアプリケーションの回復力を高めることができます。
また、生成 AI コーディングアシスタントの振る舞いゆえに、コードに存在する脆弱性が減れば AI コーディングアシスタントからの脆弱な提案も少なくなるため、コードベース内に既存するセキュリティ脆弱性の修正がさらに重要になります。