AIが生成するコードの時代におけるセキュリティテスト:QAエージェントが機能以上のものを検証すべき理由

Rui Li
AIが生成するコードの時代におけるセキュリティテスト:QAエージェントが機能以上のものを検証すべき理由 カバー

AIコーディングツールは、新たなリスクサーフェスをもたらしています。それは「正しく動作するが、デフォルトで安全でない」コードです。フォームハンドラーを生成するLLMはSQLインジェクションを考慮しません。認証フローを補完するAIオートコンプリートは権限昇格のパスを考慮しません。そのコードは機能テストをパスします。しかし3週間後、セキュリティレビューで落とされます。

これは仮定の話ではありません。AIが生成するコードがリリースされるコードの大きな割合を占めるようになるにつれ、「動作する」と「安全である」のギャップは広がっていきます。セキュリティテストは機能テストと同様に左にシフトする必要があり、AIテストエージェントがそれを実現する最適なメカニズムです。

機能テストがセキュリティ問題を検出できない理由

機能テストは、アプリケーションが想定どおりに動作することを検証します。ユーザーがフォームを送信する。データが保存される。確認画面が表示される。合格です。

セキュリティテストは、アプリケーションがすべきでないことをしていないことを検証します。未認証ユーザーが保護されたリソースにアクセスしようとする。アプリケーションはリソースではなく403を返す。スクリプトタグを含む入力は、保存前にサニタイズされる。セッショントークンはログアウト後に期限切れになる。

これらは異なる検証の問いであり、後者のカテゴリはほとんどのコードベースで体系的にテストが不足しています。エンジニアがセキュリティを気にしていないからではありません。気にしています。しかし、セキュリティテストケースの作成には時間がかかり、専門的な知識が必要であり、スプリントの速度にプレッシャーがかかると優先されにくくなります。

AIが生成するコードはリリース速度を加速させるため、この問題を悪化させます。より広い対象範囲が、より短い時間でリリースされ、セキュリティレビューがボトルネックになります。

セキュリティを考慮したAIテストエージェントが確認する内容

TestSpriteのようなテストエージェントは、機能カバレッジと並行してセキュリティに焦点を当てたテストフローを実行するよう設定できます。これはペネトレーションテストではなく、機能テストが振る舞いの不変条件を検証するのと同様に、セキュリティの不変条件を検証するアプリケーション層のチェックです。

認証と認可の境界は最も重要です。すべての保護されたルートには、未認証リクエスト、期限切れトークンを持つリクエスト、権限が不十分なユーザーからのリクエストに対して適切なレスポンスが返ることを確認する自動テストが必要です。これらのテストは自然言語で簡単に記述でき、デプロイのたびに実行されるべきです。「管理者権限を持たないユーザーが管理者ダッシュボードにアクセスしようとすると、403が返される。」

入力バリデーションは二番目の優先事項です。AIが生成したフォームハンドラーは、入力を過度に信頼しがちです。テストエージェントは、スクリプトタグ、SQLフラグメント、過大なペイロードなどの既知の悪意ある入力パターンを送信し、アプリケーションが適切に処理することを検証できます。これは包括的なセキュリティ監査ではありませんが、最も一般的な入力処理の失敗を本番環境に到達する前に検出します。

セッション管理にも独自のテストカバレッジが必要です。ログアウト時にはセッションが無効化されること、トークンのリフレッシュが同時リクエスト下で正しく動作すること、セッション状態が認証境界をまたいで予期しない形で持続しないことを確認します。

CIへのセキュリティチェックの組み込み

セキュリティを考慮したテストを実行する最適なタイミングは、機能テストと同じです。コードがマージされる前の、すべてのプルリクエストです。

セキュリティを左にシフトするとは、認可チェックと入力バリデーションのテストを、リグレッションテストと同じCIジョブに追加することを意味します。TestSpriteはこのワークフローをネイティブにサポートしており、セキュリティ不変条件テストは機能テストと同じ方法で定義され、平易な英語で記述され、同じ環境に対して実行されます。

このアプローチが定期的なセキュリティ監査やペネトレーションテストより優れている理由は、網羅性にあるわけではありません――網羅性では劣ります。優れている理由はリズムにあります。コードが変更されるたびに実行されるセキュリティチェックは、コンテキストが新鮮で修正コストが低いうちに、リグレッションをすぐに検出します。四半期ごとのセキュリティレビューは同じ問題を発見しますが、導入から数ヶ月後であり、修正には過去の調査が必要になります。

AIが生成したコードという固有の問題

開発者がCursor、Copilot、またはその他のAIコーディングアシスタントを使用する場合、自分が完全には書いておらず、完全には理解していないかもしれないコードを受け入れています。それは批判ではなく、価値提案そのものです。しかし、それは検証のギャップを生み出します。

コードを生成したのと同じAIによって書かれた機能テストは、そのAIが最適化したハッピーパスをテストする傾向があります。セキュリティのエッジケースはハッピーパスには含まれていません。「ログインフローが機能する」ことを確認するテストスイートは、「ログインフローがURLパラメータにセッショントークンを露出しない」こと、あるいは「パスワードリセットエンドポイントが有効なメールアドレスの列挙に悪用されない」ことを確認するものではありません。

TestSpriteのエージェント型アプローチがここで役立つのは、テストが実装から生成されるのではなく、「絶対に真であってはならないこと」という不変条件として人間によって定義されるからです。エージェントはコードがたまたま示す動作ではなく、契約を検証します。

小さく始めて、拡張する

初日から包括的なセキュリティテストスイートを用意する必要はありません。アプリケーション内で最も重要な3つの認証境界から始め、それぞれに対してシンプルな不変条件テストを作成しましょう。

未認証ユーザーが保護されたデータにアクセスできないことを確認する。ユーザーがリクエスト内のIDを変更することで他のユーザーのデータにアクセスできないことを確認する。管理者専用の操作が非管理者ユーザーに対して適切に失敗することを確認する。

これら6つのテストをすべてのPRで実行するだけで、AIが生成したコードがもたらすセキュリティリグレッションのかなりの割合を検出できます。そこからさらに構築していきましょう。