私は非技術系の創業者です。コードは書けません。AIだけで、2つの本番運用アプリを完全に作り上げました。
先週、自分のアプリをセキュリティの観点から自分でスキャンしました。スコアは20/100。重大な認証バイパスを含む8件の脆弱性が見つかりました。設定が欠けていると、黙ってすべてのリクエストが通ってしまうのです。
そこでVibe Checkを作りました。雰囲気でコードを書く(vibe-coded)アプリ向けの、AIパワーのセキュリティスキャナです。そして今度は、ツール自身に向けて実行しました。
The Scorecard
| Repo | スコア | 重大な指摘 |
|---|---|---|
| open-lovable (Firecrawl) | 0/100 | 3つのAPIルートすべてに対する未認証のコマンド実行 |
| Devika | 40/100 | subprocess.run()を通じてLLMの応答が実行されているが、バリデーションがない |
| Cloudflare VibeSDK | 78/100 | APIトークンが平文でログに記録されており、OAuthのCSRF保護が欠けている |
| Bolt.new | 90/100 | ユーザー制御のシェルアクション内容によるコマンドインジェクション |
| Cline | 96/100 | 軽微なCIスクリプトのコマンドインジェクション |
| Cursor | 100/100 | 問題なし |
何百万人もの人がアプリを作るのに使っているツールにも、独自のセキュリティ問題があります。もしそのコードに脆弱性があるなら、あなたのコードはどうでしょう?
Why Static Scanners Miss These
3日前、VibeDoctor がスキャナをリリースし、これらと同じレポジトリのいくつかをスキャンしました。使っていたのはSonarQube、Gitleaks、Trivy、Lighthouseで、6つのツールを並行で動かしています。Devikaは66/100のスコアでした。
私は40/100と採点し、ツールがまったく見落としていたCRITICAL(重大)なコマンドインジェクションを見つけました。
違いはアプローチです。静的スキャナは、既知の脆弱性に対するパターンマッチを行います。eval(、ハードコードされたAPIキー、古い依存関係などを探します。これは得意です。
しかし、検出できないのは意図です。
たとえば、これはDevikaから取れた実コードです:
# LLMがコマンドのリストを生成する
commands = response.split("
")
for cmd in commands:
subprocess.run(cmd.split(), capture_output=True)
eval()はありません。明らかに危険な関数呼び出しもありません。SonarQubeは、リスト引数でsubprocess.run()が呼ばれているのを見ます。これは安全なsubprocessの呼び方です。クリーンです。
ですが、そのコマンドがLLMの応答から来ています。AIが生成するものは何であれ、そのままサーバー上で実行されます。これは構文のバグではありません。意図のバグです。このコードは、書かれたとおりに動作しているだけです。ただ、そのようなことをするために書かれてはいけなかったのです。
The Bug That Started Everything
こちらは、Vibe Checkが見つけた私自身の本番運用アプリの関数です:
def _auth_ok(req: Request) -> bool:
secret = (WEBHOOK_SECRET or "").strip()
if not secret:
return True # シークレットが未設定 -> すべて許可
...
私がこのコードに対して実行した静的ツールはすべて「クリーン」と言いました。ハードコードされたシークレットはありません。SQLインジェクションもありません。XSSもありません。コードは構文的に完璧でした。
バグの中身:WEBHOOK_SECRET が環境変数に設定されていないと、この関数は True を返し、すべてのWebhookリクエストが認証されてしまいます。開発環境では、この変数が未設定になっていることがよくあります。本番環境では、環境変数のタイプミスひとつでバックエンドが丸ごと公開されます。
これはセマンティック(意味論)バグです。コードを読んで「入力が欠けたら何が起きるのか?」と問いかけることでしか見つけられません。
How Vibe Check Works
Vibe Checkは、セキュリティに焦点を当てたプロンプトとともにあなたのコードをClaude(AnthropicのAI)へ送信します。プロンプトは6つのカテゴリ、つまりシークレット、認証、インジェクション、データ露出、依存関係、設定をカバーしています。
そのプロンプトには、AIコード生成ツールが作りがちなバグに関する具体的な指示があります:
-
デフォルト許可パターン。
if not secret: return Trueを重大としてフラグを立てる。 - LLM出力を実行の入力として扱う。 モデル出力が、バリデーションなしでsubprocess、eval、またはファイル書き込みへ到達する経路をすべてフラグする。
- アクション用エンドポイントでの認証の欠落。 認証チェックなしで破壊的なアクションを実行するルートをフラグする。
出力はAnthropicのツール利用APIを通じて構造化されます。すべての指摘にはカテゴリ、重大度、ファイル、行番号、説明、そして提案される修正が含まれます。すべて平易な英語です。
False Positives Are the Real Product
LLMは騒がしい(ノイズの多い)セキュリティ査読者です。自己スキャンの1日でClaudeは次を指摘しました:
"render.yaml contains
sync: falsefor secrets — could be misconfigured"
(sync: false はRender.comのシークレット設定として正しいものです。)
"compare_digest is correctly implemented"
(それが文字通り解決策なのに、指摘としてフラグが立てられます。)
解決策は、プロンプトを増やすことではありません。Claudeは、ガードレールを無視する確率が3分の1程度あります。真の解決策はハードな事後パースフィルタで、既知の誤検知パターンに一致する指摘を落とすことです:
- インフラ設定ファイル(低〜中の重大度)
- テンプレートファイル(シークレットカテゴリの指摘用)
- テストファイル全部
- 自己矛盾する説明(「Xは正しいが…」)
- 憶測によるヘッジ(「〜かもしれない」「潜在的に許可してしまう」)
- 開発環境だけの警告
重大(critical)な重大度は決してフィルタしません。重大度がcriticalの誤検知は、人間のレビューのために表に出したいのです。
このフィルタの後、Vibe Checkの自社レポは指摘ゼロの100/100としてスキャンされます。フィルタがないと、実行のたびに見つかる指摘が変わり、79〜94の間を行き来していました。
The Numbers Behind the Problem
これは机上の空論ではありません:
- 65%のvibe-codedな本番運用アプリにセキュリティ問題がある(Escape.tech、1,400件のアプリをスキャン)
- 45%のAI生成コードにOWASP Top 10の脆弱性が含まれる(Veracode、100+のLLMをテスト)
- 35件のCVEが、2026年3月だけでAI生成コードにトレースされた(Georgia Tech Vibe Security Radar)
- 150万のAPIキーが、あるvibe-codedアプリからローンチ後3日以内に漏えい(Moltbook)
最後の数字が最も重要です。ほとんどのバイブ・コーダーは、自分たちが出荷しているコードを読み取ることができません。監査することもできません。ログインページがバイパスできるかどうかも判断できません。
私はその一人です。コードを1行も書かずに、本番アプリを2つ作りました。コードが脆弱だということは、スキャンするまでまったく知りませんでした。
The Loop
Vibe Checkが可能にすることは次のとおりです:
- Scan(スキャン) — GitHubのURLを貼り付けると、60秒でスコアを取得
- Download(ダウンロード) — 調査結果をmarkdownファイルとして取得
- Fix(修正) — 調査結果をAIコーディングツール(Cursor、Claude Code、Lovable、など)に貼り付ける
- Re-scan(再スキャン) — 修正が機能したことを確認し、スコアが上がったかを検証
私自身のアプリは20/100から、修正後に動く状態になりました。スキャナーが、私に見えていなかった点を見つけてくれました。AIコーディングツールが、スキャナーが見つけた内容を修正しました。再スキャンで、修正が機能していることが確認できました。
これがプロダクトです。スキャン。修正。検証。
Try It
Vibe Checkは無料です。最初のスキャンはサインアップ不要です。コードは保存されません——スキャンして結果を報告し、その後は忘れます。
https://chat-api-19ij.onrender.com
evance1227/chatでコードはオープンソースです。
リポジトリをスキャンしてください。完璧に動いているコードの中に、何が隠れているのか驚くかもしれません。
— Elise Vance(@shecantcode)



