こんにちは。株式会社エーアイセキュリティラボで、SaaS 型 Web アプリケーション脆弱性診断プラットフォーム「AeyeScan」の開発エンジニアをしている有馬です。
バイブコーディング(AIに自然言語で指示してコードを書かせる開発スタイル)が当たり前になりつつある今、AIが生成したコードのセキュリティは実際どうなのか。推測ではなくデータで答えを出したくて、ひとつ検証をしてみました。Claude に EC サイトをゼロから作らせて、完成したアプリを自社の AeyeScan でスキャンする、というものです。
先に結論だけ書きます。Critical・High の脆弱性は 0 件。でも、24 件の問題が見つかりました。その内訳を見ていくと、「AIはセキュリティを知らないのではなく、セキュリティを気にしない」という構造が見えてきました。
●[検証の概要]作ったもの
EC サイト実装用のプロンプト自体も Sonnet 4.6 に生成させています。こちらから指定したのは Next.js・Express・shadcn/ui という大枠と、EC サイトとしての基本機能、ローカル環境で動かすことだけです。
セキュリティに関する指示は一切入れていません(実際に使用したプロンプトは転載元を参照)。
● AIが実際に生成したアプリの構成
レイヤー/技術
フロントエンド/Next.js 16 (App Router) + TypeScript + Tailwind CSS
UIコンポーネント/shadcn/ui + lucide-react
フォーム管理/react-hook-form + zod
バックエンド/Express.js 4.18.3
データベース/SQLite (better-sqlite3)
認証/JWT + bcrypt
会員登録・ログイン、商品一覧・検索、カート管理、注文確定、レビュー投稿、管理者ダッシュボードなど、EC サイトとして一通りの機能を持っています。こちらから指定したのはフレームワークと基本機能だけで、それ以外のライブラリ選定や具体的な実装はすべてAIに任せました。
● スキャン方法
完成したアプリをローカル開発環境で起動し、AeyeScan のWebアプリケーションスキャンを実施しました。
・対象画面数: 40画面
・スキャンルールセット: Webアプリケーションスキャン(OWASP TOP 10 全カテゴリ対応)
AeyeScanとは?
AeyeScanは、クラウド型のWebアプリケーション脆弱性診断ツールです。対象サイトをブラウザで自動巡回し、IPA「安全なウェブサイトの作り方」やOWASP TOP 10などの基準に沿った脆弱性検査を実施します。
● スキャン結果のサマリー
全体評価: Medium
深刻度:件数
Critical:0件
High:0件
Medium:2件
Low:4件
Info:18件

Critical も High もゼロ。ぱっと見は悪くない結果に見えます。しかし、この数字の中身を掘っていくと、バイブコーディングの「クセ」がはっきり見えてきます。
● 特に注目すべき検出結果
24件すべてを列挙するのではなく、「バイブコーディングの特徴」が顕著に表れているものに絞って紹介します。
クリックジャッキング(Medium / CVSS 5.3)
会員登録フォーム(/register)が外部サイトにiframe(別のWebページの中にページを埋め込む仕組み)で埋め込める状態でした。

攻撃者が罠サイト上に透明な iframe を重ねれば、ユーザーに気づかせないまま送信ボタンをクリックさせることができます。
原因: Content-Security-Policy の frame-ancestors ディレクティブ(ブラウザに「このページは外部サイトに埋め込まないで」と伝えるセキュリティヘッダ)が設定されていませんでした。この設定は明示的に行う必要がありますが、AIはこれを行っていませんでした。
● セキュリティミドルウェアの「入れただけ」問題
今回の検証で一番印象的だった発見です。
スキャン結果にはセキュリティヘッダの不備(CSP、X-Content-Type-Options、Referrer-Policy等)が多数含まれていました。原因を探るためにソースコードを確認したところ、こうなっていました。
// server.js の実際の内容 - helmet のインポートも適用もない
app.use(cors({ origin: true, credentials: true }));
app.use(pinoHttp({ logger }));
app.use(express.json());
// ← ここに app.use(helmet()) があるべきだった
AIは Express のセキュリティミドルウェア「Helmet」(セキュリティ関連の HTTP ヘッダをまとめて付与してくれるライブラリ)を package.json にインストールしていたものの、app.use(helmet()) を書いていなかったのです。同様に、レート制限ミドルウェアの express-rate-limit も依存関係に追加されているのに、実際のコードでは一切使われていませんでした。
「セキュリティに必要なパッケージを知っていて、インストールまではする。でも実際に適用するコードは書き忘れる」——これがバイブコーディングの典型的な落とし穴だと感じました。
● パスワード強度の不備
7 文字のパスワード user123 で会員登録が成功してしまいました。実装を確認すると 6 文字以上のバリデーションは存在していたものの、OWASP(Webセキュリティの国際的な基準を策定する団体)の基準では最低 8 文字以上が推奨されており、さらによくあるパスワードを拒否する仕組みも必要です。基準が緩すぎる状態でした。
● デバッグ情報の露出
Express側のエラーハンドラが、スタックトレースをそのままクライアントに返していました。
// server.js のエラーハンドラ
res.status(500).json({
error: err.message,
stack: err.stack, // ← サーバーのディレクトリ構造がそのまま返される
});
攻撃者にアプリの内部構造を教えてしまう実装です。本番では NODE_ENV で出し分けるべきですが、その考慮もありませんでした。
● 未検出だった項目にも注目する
検出された問題と同じくらい大事なのが、検出されなかった項目です。
IPA「安全なウェブサイトの作り方」の11カテゴリ中、クリックジャッキング以外の10項目はすべて合格していました。

SQLインジェクション、XSS、CSRF、ディレクトリ・トラバーサルといった致命的な脆弱性はすべて未検出でした。実際にソースコードを確認すると、データベースへのクエリはすべて better-sqlite3のprepared statement(SQL文にユーザー入力を安全に埋め込む仕組み)で記述されており、ユーザー入力が直接 SQL に結合される箇所はありませんでした。AIが意識的にセキュリティ対策を施したというよりも、フレームワークの標準的な書き方に従った結果、自然と防がれていたと考えられます。
● 結果から見えるバイブコーディングの構造的な特徴
ここまでの結果を整理すると、ひとつの構造が浮かんできます。
フレームワークが自動で守る領域(XSS、SQL インジェクション等)は問題なし。一方で、明示的に設定しなければ効かない防御(CSP、パスワードポリシー等)は軒並み抜けている。
そして検出された問題には共通点があります。どれも「なくてもアプリは動く」ものばかりです。CSP ヘッダがなくてもサイトは表示されますし、パスワードが7文字でも登録は通りますし、Helmet が未適用でも Express は起動します。
AIは「動くものを作る」ことには長けています。ただ、動作に影響しないセキュリティ設定は、こちらから頼まない限り後回しにされます。Helmet をインストールする判断力はあるのに、app.use(helmet()) の一行は書かない。「知っている」と「最後までやりきる」の間にギャップがあるのです。
● バイブコーディング時代のセキュリティ対策
今回の検証から得た教訓を4つにまとめます。
1. セキュリティ要件をプロンプトに含める。「EC サイトを作って」ではなく、「Helmet を適用して」「CSP の frame-ancestors を設定して」「パスワードは 8 文字以上で」と具体的に指示します。これだけで AIの出力は大きく変わります。
2. 「インストール済み」と「適用済み」を区別する。 package.json にあるからといって使われているとは限りません。Helmet と express-rate-limit がまさにそうでした。セキュリティライブラリが実際にコード上で適用されているかを確認することが重要です。
3. フレームワーク任せで安心しない。 Next.jsが XSS を防いでくれるのは事実ですが、それはフレームワークの守備範囲の話です。CSP ヘッダやパスワードポリシーなど、フレームワークの「外側」にあるセキュリティは明示的に実装する必要があります。
4. スキャンツールで機械的にチェックする。 40 画面のアプリで 24 件。目視では拾いきれない数です。AIで速く作り、スキャンツールで網羅的に検査し、人間が最終判断する。この 3 段階のサイクルが現実的なやり方だと考えています。
● まとめ
AIに EC サイトを作らせてスキャンした結果、見えたのは「AIは賢いが、気が利かない」ということでした。
致命的な脆弱性はゼロ。フレームワークが守ってくれる領域は問題ありません。しかし Helmet は入れただけで適用し忘れていますし、パスワードは 7 文字で通ります。全部「動作には関係ないけど、セキュリティ上は問題」なものばかりです。
「動くものを作る」と「安全なものを作る」の間にはギャップがあります。そのギャップを埋めるのは、今のところまだ人間の仕事です。

