生成AIによる開発の華やかな成功事例の裏には、世界中のハッカーから狙われるという現実があります。AIが生成するコードは、情報の正確性を検証するわけではないため、一見すると正しく動作するものの、セキュリティ上の欠陥を抱えたコードを平然と生成してしまうのです。この連載では、開発の間口が広がった今こそ、セキュリティの重要性を再確認し、安全に開発を続けるための実践的な解決策を提供します。第2回では、AIが生成したコードに直接現れやすい、古典的かつ具体的な脆弱性を「OWASP Top 10」から抜粋して解説します。開発者がAIの提案を鵜呑みにし、「動くコード」を「安全なコード」と勘違いしてしまう典型的なパターンに焦点を当て、その危険性と対策を明らかにしていきます。
「動くコード」が「安全なコード」とは限らない現実
前回は、バイブコーディングに潜むセキュリティリスクの具体例を解説しました。生成AIは、ソフトウェア開発の生産性を劇的に向上させましたが、その速度と引き換えに、私たちは従来からあるセキュリティリスクを見過ごしがちになっています。
AIの学習データはインターネット上の膨大なコードに依存しており、その中には古く脆弱なサンプルコードも数多く含まれています。これは、OWASP Top 10 for LLM Applicationsで指摘されている「LLM09:偽情報」のリスクの一側面でもあります。
AIによって生成されたコードは、情報の正確性を検証するわけではなく、統計的にもっともらしいシーケンスを生成します。そのため、一見すると正しく動作するものの、セキュリティ上の欠陥を抱えたコードを意図せず生成してしまうのです。
本記事では、AIが生成したコードに直接現れやすい、古典的かつ具体的な脆弱性を、Webアプリケーションの重大なセキュリティ脅威をランク付けした「OWASP Top 10」から抜粋して解説します。
開発者がAIの提案をそのまま受け入れ、「動くコード」を「安全なコード」と勘違いしてしまう典型的なパターンに焦点を当て、その危険性と対策を明らかにします。
AIには理解できない「データの所有権」
A01:2021-アクセス制御の不備
アクセス制御の不備は、アプリケーションのロジックにおいて、認証されたユーザーが権限外の機能やデータにアクセスできてしまう脆弱性を指します。「誰が(主体)」「どの情報に(リソース)」「何をしてよいか(権限)」という認可ロジックの欠陥が原因で発生します。
AIは、アプリケーション全体のビジネスロジック、役割(Role)、そしてデータの所有権といった、人間が意図しているコンテキストを完全には理解していません。
そのため「ユーザー情報を表示するAPIを作成して」と依頼すると、データの所有権についてはプロンプトでは触れられていないため、本来は閲覧できないユーザーにも情報を渡してしまうコードを生成する可能性があります。
具体的な例としては、ログイン必須や管理者アカウント限定のページに対して適切なアクセス制御が正しく設置されておらず、誰でもアクセスができてしまうといったケースが考えられます。
具体例:BaaSにおける認可ルールの不備
連載の第一回でも軽く触れましたが、BaaS(Backend as a Service)のセキュリティルール設定は、この脆弱性が現れやすい典型的な例です。
開発初期段階のサンプルとして、「誰でも読み書き可能」あるいは「認証ユーザーなら誰でもOK」といった、データの所有者を無視した安易なルールのまま開発が進んでしまうことがあります。
脆弱な設定例(Firebase/Supabase)
-
誰でも読み書き可能:allow read, write: if true;
- ルールが緩すぎます。さらにディレクトリリスティングも有効になっているためファイルの一覧にアクセスできてしまいます。
-
認証ユーザーなら誰でもアクセス可能:allow read, write: if request.auth != null;
- このルールでは、ユーザーAがユーザーBのデータを自由に読み書きできてしまいます。
安全な実装例(Supabase RLS)
行レベルセキュリティ(RLS)を用いて、「自分のデータにしかアクセスできない」というポリシーをアプリケーションロジックの一部としてデータベースレベルで強制することが不可欠です。
-- profilesテーブルでRLSを有効化 ALTER TABLE profiles ENABLE ROW LEVEL SECURITY; -- 認証ユーザーが自身のプロフィールのみを閲覧・更新できるポリシーを作成 CREATE POLICY "Users can view their own profile." ON profiles FOR SELECT USING (auth.uid() = user_id); CREATE POLICY "Users can update their own profile." ON profiles FOR UPDATE USING (auth.uid() = user_id);
このように、データベースとAPIエンドポイントレベルで、リクエストされたリソースの所有者が、操作を実行しているユーザーと一致することを常に検証する必要があります。
この記事は参考になりましたか?
- 生成AI時代のセキュリティ入門連載記事一覧
-
- 【「コーダー」から「監督者」へ】「バイブコーディング」で脆弱性を持ち込まないためのマインド...
- AIエージェントの死角。「依存関係の脆弱性」と「サプライチェーン攻撃」からプロジェクトを守...
- AIが生成したコードに潜む古典的セキュリティホールを解説!セキュリティ設計の基本を知ろう
- この記事の著者
-
Kyohei Fukuda(キョウヘイ フクダ)
広島県出身、東京在住のWebエンジニア。 国内IT企業数社でフロントエンド開発に従事した後、現在は外資IT企業でSolution Engineer兼Developer Advocateを務めている。OSSのPDF生成ライブラリ「pdfme」を開発し、関連する書類作成サービスを個人開発し運営。 JavaSc...
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
CodeZine編集部(コードジンヘンシュウブ)
CodeZineは、株式会社翔泳社が運営する開発者のための情報メディアです。日々の開発に取り組むエンジニアやテクノロジーを学びたい方に向けて、プログラミングやAI活用、開発ツール、エンジニアの学びとキャリアに関する記事をお届けしています。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
