AI コーディングツールのためのセキュリティチェックポイントです。AI アシスタントが書き込むすべてのファイルをチェックし、危険なものはディスクに書き込まれる前に止めます。
AI コーディングアシスタント(Claude Code、Codex など)は高速にコードを書きますが、その中にはパスワード、メールアドレス、API キー、生のユーザー入力を扱うコードも含まれます。アシスタントが、セキュリティを考慮せずにそれらのデータをデータベースクエリ、シェルコマンド、HTTP レスポンスに直接流し込んでしまうのは簡単です。
VibeGate はアシスタントとファイルシステムの間に位置します。アシスタントがファイルの書き込みや編集を試みるたびに、VibeGate は新しいコードをまずスキャンします。
分析自体には LLM は一切関与しません。高速で決定論的な静的解析であり、誤った情報を作り出すことはなく、トークンを消費することもありません。
以下が VibeGate が現在チェックするすべての項目です:
| チェック | 検出するもの | 結果 |
|---|
| コマンドインジェクション | サニタイズされていない入力がシェルコマンドに到達 | ブロック |
| SQL インジェクション | サニタイズされていない入力がデータベースクエリに到達 | ブロック |
| NoSQL インジェクション | リクエストボディがそのままデータベースフィルタとして使用される | ブロック |
| テンプレートインジェクション (SSTI) | テンプレートのソース自体(データだけではなく)がユーザー入力に由来する | ブロック |
| 安全でないデシリアライゼーション | 信頼できないデータが安全でないデシリアライザ(pickle、安全でない YAML など)に到達 | ブロック |
| パストラバーサル | サニタイズされていない入力がファイル読み取り・書き込み・削除に到達 | ブロック |
| XXE | 信頼できない XML が外部エンティティを有効にしてパースされる | ブロック |
| XSS | サニタイズされていない入力が生の HTML としてレンダリングされる | ブロック |
| 制限のないファイルアップロード | アップロードされたファイル名がそのまま保存パスに使用される | ブロック |
| SSRF | サーバーがハードコードされていない URL を取得する | 警告 |
| オープンリダイレクト | ハードコードされていないリダイレクト先 | 警告 |
| マスアサインメント | リクエストボディ全体がモデルコンストラクタや更新処理に渡される | 警告 |
| リクエストボディ内の機密データ | リクエストボディから読み取られたメールアドレス、パスワード、トークンなど | 警告 |
| URL/クエリ内の機密データ | クエリ文字列から読み取られたメールアドレス、パスワード、トークンなど | 警告 |
| ヘッダー内の機密データ | リクエストヘッダーから読み取られたメールアドレス、パスワード、トークンなど | 警告 |
| ユーザー入力からのファイルパス | ハードコードされた文字列ではなく変数がファイルパスとして使用されている | 警告 |
| CLI 引数 | データがコマンドライン引数から来ている | 警告 |
| 標準入力 | データが標準入力から来ている | 警告 |
| 環境変数 | データが環境変数から来ている | 警告 |
| コミットSHAで固定されていないGitHub Action | ワークフローがコミットSHAではなく可変タグ(@v4)を使用している | 警告 |
安全でない pull_request_target | ワークフローが pull_request_target トリガーを使用している | 警告 |
| 資格情報のログ出力 | パスワード、API キー、トークンが print/console.log/ロガーに渡されている | 警告 |
| ハードコードされた秘密情報 | 秘密情報らしい名前の変数に、実際のリテラル値が代入されている | 警告 |
完全な最新リストは guidance.TECHNICAL_RISKS と formatter.BLOCKING_CATEGORIES にあります。この表が古くなった場合に備えてください。
┌───────────────────────────────┐
│ Claude Code にファイルの │
│ 作成または編集を依頼 │
└───────────────┬───────────────┘
│
▼
┌───────────────────────────────┐
│ Claude Code がファイルを │
│ 保存しようとする(Write/Edit │
│ ツール) │
└───────────────┬───────────────┘
│
▼
┌───────────────────────────────┐
│ VibeGate フック │
│ (自動実行、ファイル保存前)│
└───────────────┬───────────────┘
│
Semgrep で新しいコードをスキャン
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌────────────────────┐ ┌────────────────────┐ ┌──────────────────────┐
│ リスクのある入力 │ │ リスクのある入力 │ │ リスクのある入力が │
│ なし │ │ だがリスクは低い │ │ 重大なシンクに到達 │
│ │ │ (例:HTTP 応答に │ │ (SQL/コマンド/RCE、│
│ │ │ 表示される) │ │ テンプレート注入)│
└─────────┬──────────┘ └─────────┬──────────┘ └───────────┬──────────┘
│ │ │
▼ ▼ ▼
ファイルは保存、 ファイルは保存、 ファイルは保存されない。
何も表示されない。 さらにターミナルに Claude Code は
警告(リスクと修正方法) ブロック理由を確認し、
が表示される。 何を修正すべきか指示される。
つまり、安全なコードはそのまま通過し、リスクはあるが許容できるコードは警告付きで保存され、SQLインジェクション、コマンドインジェクション、リモートコード実行などに一歩手前のコードはディスクに書き込まれる前に止められます。
VibeGate 自体で予期しないエラーが発生した場合は、常に書き込みを許可します。フックのバグが作業をブロックする理由になってはいけません。
すべての警告とブロックには、Claude Code が発見を黙って修正するのではなく、応答でユーザーに明示的に伝えるよう指示する命令も含まれています。これにより、VibeGate の活動は、わざわざ調べに行かなければならないターミナルログだけでなく、会話の中でも可視化されます。
| VibeGate が検出したもの | 結果 |
|---|---|
| ユーザー入力がない、またはまだサポートしていない言語 | ファイルは通常通り保存、何も表示されない |
| ユーザー入力が検出されたが、リスクは中程度(例:オープンリダイレクト、マスアサインメント) | ファイルは保存、ターミナルに警告+ガイダンスが表示される |
| ユーザー入力がサニタイズされずに重大なシンク(SQL/NoSQL クエリ、シェルコマンド、テンプレートエンジン、デシリアライザ、XML パーサ、ファイルパス、アップロードされたファイル名、または生の HTML 出力)に流れ込む | ファイルは保存されない — Claude Code に理由が伝えられる |
何がブロックされ、何が警告のみかについては、上記の「これが解決する問題」の表を参照してください。
現在、VibeGate は Python、JavaScript/TypeScript、Go、Java、PHP、Ruby を理解し、Claude Code および Codex に接続します。コアロジックに手を加えずに、さらに多くの言語やツールを追加できます。
また、GitHub Actions ワークフローファイルについて、2 つの一般的な CI/CD サプライチェーンのミスをチェックします。アクションがコミット SHA ではなく可変タグ(@v4)に固定されている場合と、安全でない pull_request_target トリガーです。どちらも、積極的なエクスプロイトの証拠ではなく、強化チェックであるため、警告のみ行います。
以下は、VibeGate を常時稼働させながら、Claude Code が RSS フィードリーダーアプリをゼロから構築する実際の録画です。Claude Code が停止し、VibeGate がフラグした内容とその理由を明示的に述べてから続行する瞬間に注目してください。フィード取得コードにおける実際の SSRF リスクをその場で修正する場面も含まれています。
以下は静止画での 2 つ目の例です。Claude Code が、写真をアップロードしてその詳細を表示できるアプリを構築しています。VibeGate は、ファイル名やその他のファイル詳細が後で画面に表示されることに気づき、これがページに有害なコードを注入するために使用される可能性がある(これは XSS と呼ばれます)と警告します。Claude Code は、情報が安全に表示されるようにコードを調整します。
どちらの場合も、理由もなくブロックされることはなく、誰もコードを 1 行ずつ読んで問題を発見する必要もありませんでした。VibeGate はファイルが書き込まれた瞬間に捕捉し、AI がその場で修正しました。
AI アシスタントにより安全なコードを書かせる方法は 2 つあります。1 つは、開始前にセキュアコーディングに関する大量の指示(SQL インジェクション、XSS、パスワード処理、ファイルアップロードなどを網羅したチェックリストなど)を会話に読み込む方法です。もう 1 つは VibeGate のやり方です。ファイルが書き込まれるときに自動的にコードをチェックし、実際に問題がある場合にのみ発言します。
最初のアプローチは、必要かどうかに関わらず、すべてのメッセージに対してトークンを消費します。複数のリスクカテゴリをカバーする典型的なセキュアコーディングチェックリストは、簡単に数千トークンを追加します。AI アシスタントが 1 セッションで 50 ファイルを書き、そのたびにチェックリストが再読み込みされたりコンテキストに保持されたりすると、ほとんどの場合、今まさに書き込まれているファイルには適用されないアドバイスに対して、10 万トークンを超えるコストを支払う可能性があります。ログインページと単純な色定数ファイルには同じ警告は必要ありませんが、読み込まれたチェックリストは事前にそれらを区別できません。
VibeGate はこれを逆転させます。リスクのあるパターンが含まれていないファイルについては沈黙し、余分なコストはかかりません。何かを見つけた場合(ユーザー入力がデータベースクエリに流れ込むなど)にのみ、その 1 つの問題に関する短く具体的なメモを追加します。これは通常、完全なチェックリストのサイズのごく一部です。つまり、すべてのファイルに対して一定のトークンコストを支払うのではなく、実際に注意が必要なファイルにのみ小さなコストが発生し、そのコストは見つかった問題に正確に向けられ、セキュリティに関する一般的な講義ではありません。
これにより、ガイダンスの信頼性も向上します。100 行のコードを書きながら「セキュリティに注意してください」と指示された AI アシスタントは、多数の行の中からリスクのある 1 行を見逃す可能性があります。ゲートは疲れたり注意が散ったりしません。毎回、同じ固定ルールを使用して、すべての書き込みをチェックします。
一度インストールするだけです。これにより、VibeGate が依存する Semgrep も一緒にインストールされます。
pipx install git+https://github.com/theMiddleBlue/vibegate
次に、保護したいプロジェクト内で有効にします。
cd your-project
vibegate on # ここで有効にする(その後 Claude Code をリロード)
vibegate status # このプロジェクトで有効かどうかを確認
vibegate off # ここで無効にする
vibegate on は、Write|Edit|MultiEdit に対する PreToolUse フックをそのプロジェクトの .claude/settings.local.json に追加します。プロジェクト単位でスコープが設定されるため、1 つのリポジトリで有効にしても他のリポジトリには影響しません。
Claude Code はフックを vibegate run --host claude_code として実行します。絶対パスは含まれないため、再インストールや移動後も動作し続けます。
vibegate status は、このプロジェクトで VibeGate が実際に捕捉した内容の実行ログも表示します。すべての警告とブロックが、ファイル、行、カテゴリとともに表示され、有効かどうかだけでなく、時間経過に伴うアクティビティを確認できます。
$ vibegate status
█ █ █████ ████ █████ ████ ███ █████ █████
...
● VibeGate は .claude/settings.local.json で有効です
最近のアクティビティ(記録された 2 件中、最新順):
2026-07-02T17:35:48+00:00 ⛔ BLOCKED server.py:3 EXEC_INPUT (FREE_TEXT)
2026-07-02T17:35:46+00:00 ⚠ WARNED app.py:2 HTTP_BODY (EMAIL)
このログはプロジェクトルートの .vibegate/activity.jsonl に保存されます。.gitignore に追加してください。これはローカルの開発者状態であり、コミットするものではありません。
VibeGate は、明示的な --host <name> フラグ、次に VIBEGATE_HOST 環境変数、次に受信ペイロードからの自動検出の順で、どのホストと通信しているか判断します。デフォルトは claude_code です。
VibeGate が意識的に安全だと判断した何かにフラグを立てた場合は、同じ行に vibegate-ignore コメントを追加してください。これはあらゆるコメント構文(#、// など)で動作します。VibeGate はテキストを探すだけだからです。
query = f"SELECT * FROM users WHERE id = {user_id}" # vibegate-ignore
その行のすべてではなく特定のカテゴリのみを抑制するには、コロンの後にカテゴリを列挙します(技術カテゴリまたはセマンティックタイプのいずれかに一致、カンマ区切り、大文字小文字を区別しません)。
query = f"SELECT * FROM users WHERE id = {user_id}" # vibegate-ignore: DB_QUERY
src/vibegate/
├── hook.py # エントリポイント
├── cli.py # on/off/status コマンド + ASCII バナー
├── activity_log.py # 警告/ブロックを .vibegate/activity.jsonl に保存
├── colors.py # 共有 ANSI カラーコード(レポート + CLI バナー)
├── core.py # ホストに依存しないパイプライン
├── models.py # InputEvent / ClassifiedFinding / AnalysisResult
├── semgrep_runner.py # Semgrep をサブプロセスとして実行(フェイルセーフ)
├── classifier.py # Semgrep ルール→カテゴリ、変数名→データ型 のマッピング
├── guidance.py # 静的リスク/修復の解説
├── formatter.py # 結果をターミナルレポート + ホストコンテキストに変換
├── adapters/ # base, claude_code, codex + 小さなレジストリ
└── rules/ # Semgrep ルール — 言語ごとに 1 ファイル(Python、JS/TS、
# Go、Java、PHP、Ruby)+汎用プレースホルダ
パイプライン自体(core.py)は特定のホストと直接通信しません。ホスト固有の入出力はすべて adapters/ にあり、新しいホストを追加するために解析ロジックに触れる必要はありません。
semgrep --validate --config src/vibegate/rules/ # ルールが有効か確認
pytest tests/ # 単体テスト + 結合テスト
Claude Code なしでエンドツーエンドの動作を確認するには:
python3 -c 'import json; print(json.dumps({"tool_name":"Write","tool_input":{"file_path":"/tmp/t.py","new_content":"email = request.json.get(\"email\")"}}))' \
| python3 src/vibegate/hook.py --host claude_code
rules/<lang>-user-input.yaml を追加し、新しいルール ID を classifier.RULE_TO_TECHNICAL に登録し、core.EXT_TO_LANGUAGE でファイル拡張子をマッピングします。classifier.VARNAME_TO_SEMANTIC にキーワードを追加し、guidance.SEMANTIC_GUIDANCE に解説を追加します。RULE_TO_TECHNICAL へのエントリ、guidance.TECHNICAL_RISKS へのカードを追加します。adapters/ 下にアダプタを追加し、adapters/__init__.py に登録します。codex アダプタは初期のベストエフォートのマッピングです。何かをブロックするために使用する前に、イベントコントラクトを Codex のバージョンと照合して確認してください。"requires login" を返すため、classifier はファイル内容と行番号からスニペットを再構築します。Edit/MultiEdit では、claude_code アダプタがディスクから編集後の完全なファイルを再構築するため、汚染されたソースと別の編集で導入されたシンクがまだ接続されています。ただし、その編集で実際に触れた行の所見のみが報告されます。シンクが既に存在し、後続の編集でそれに到達する汚染されたソースのみが追加された場合、それは捕捉されません(シンクの行は新しい編集の一部ではなかったため)。この再構築は Claude-Code 固有です。codex アダプタはまだこれを行いません。