Claude Media
Claude Code security-reviewでブランチの脆弱性を検知する

Claude Code security-reviewでブランチの脆弱性を検知する

security-reviewはブランチの差分をorigin/HEADと比較し、インジェクションや認証不備、データ漏出などの脆弱性を検知するコマンドです。originリモートが無いと失敗し、対処には3つの手順があります。

security-reviewは、現在のブランチにある変更を、インジェクション・認証不備・データ漏出といったセキュリティ観点で調べるClaude Codeのコマンドです。ブランチとorigin側のデフォルトブランチとの差分を対象にするため、originリモートが無いプロジェクトでは失敗します。/code-reviewとの違い、ambiguous argumentエラーの直し方、比較先がずれたときの見え方を、gitを実際に動かした結果つきで扱います。正確性・簡潔性のレビューを扱う/code-reviewの実行経路はClaude Codeコードレビュー — 4つの実行経路の使い分けで解説しています。

security-reviewは何を検知し、何を見ないのか

/security-reviewは、現在のブランチにある変更をセキュリティの観点で分析するコマンドです。コマンド一覧の説明は「ブランチとoriginのデフォルトブランチとの差分をレビューし、インジェクション・認証の問題・データ漏出といったリスクを特定する」です。対象は差分そのもので、リポジトリ全体を毎回スキャンするわけではありません。

差分に入っていない既存コードは、この1回では見ません。セキュリティのドキュメントには、既に手元にあるコードを調べたいときの案内があります。セッション内で特定のファイルやディレクトリの脆弱性確認をClaudeに頼むか、リポジトリ全体を対象にするClaude Securityプラグインの複数エージェントスキャンを使う、という書き分けです。どちらの場合も読むのはチェックアウトしたソースコードで、動いているサイトやデプロイ済みのサービスは調べません。

/security-reviewは、/code-reviewや/verifyと違い、コマンド一覧にSkillの表記が付いていません。一方でスキル機構とは無関係でもありません。エラー文の形(Shell command failed for pattern "!…")は、スキルの動的コンテキスト注入が失敗したときの表記と同じです。スキルのドキュメントには、組み込みコマンドのうち/initと/security-reviewはSkillツール経由で呼べる、という記載もあります。/compactなどはこの対象外です。

設定のdisableBundledSkillsをtrueにすると、/initなどの組み込みコマンドは手入力できてもモデルからは見えなくなります。

同名のGitHub Action版(anthropics/claude-code-security-review)も配布されています。CLIのコマンドとは別の実装で、Haikuモデル廃止の影響で誤検知フィルタが無音のまま無効になる不具合が報告されています。詳細はsecurity-reviewのHaiku廃止で誤検知フィルタが無効化する理由にあります。

出荷前の流れと、ほかのセキュリティ層との置き場所

コマンド一覧は、出荷前の作業を次の順で挙げています。

流れ

出荷前の3コマンド

  1. 1

    /diff で変更内容を確認する

    作業ツリーの変更を、Claudeが入れた編集も含めて見直します。

  2. 2

    /code-review で正確性を見る

    正確性のバグを洗い出します。--fixで指摘を適用でき、PR番号を渡せばPRも対象にできます。

  3. 3

    /security-review で脆弱性を見る

    仕上げに、ブランチの差分をセキュリティの観点で確認します。

security-guidanceプラグインのドキュメントには、セキュリティ確認の層を並べた表があります。/security-reviewの位置は「1回きりの単発確認」です。

段階手段守備範囲
セッション内手段security-guidanceプラグイン守備範囲Claudeが書くコードの典型的な脆弱性を、同じセッションで修正
手動(単発)手段/security-review守備範囲現在のブランチに対する1回のセキュリティ確認
手動(深掘り)手段Claude Securityプラグイン守備範囲リポジトリや差分の複数エージェントスキャン
PR時手段Code Review(TeamとEnterpriseプラン)守備範囲コードベース全体の文脈を使う正確性・セキュリティレビュー
常時監視手段Claude Security(Enterpriseプラン)守備範囲接続したリポジトリを監視するホスト型スキャン
CI手段既存の静的解析・依存関係スキャナ守備範囲言語固有のルールやサプライチェーン検査

プラグインの側は、編集のたびにパターン照合を走らせ、ターンの終わりにモデルレビューをかけ、ClaudeがBashツールで行うcommitやpushのたびに深いレビューを行います。自分のシェルで打ったcommitは、セッション内の!シェルエスケープも含めて対象外です。仕組みと導入はClaude Code security-guidanceで脆弱性を自動検知するにまとめています。権限設計やサンドボックスなど、Claude Code自体のセキュリティ設定はClaude Codeセキュリティ・権限ガイドの領分です。

/security-reviewが拾えない状況でも、Claude Securityプラグインの差分スキャンは、ブランチの差分、PRの差分、単一コミットを対象にできます。コマンドは/claude-securityで、/plugin install claude-security@claude-plugins-officialで入れます。スキャンされるのはコミット済みの変更だけなので、作業中の編集は先にcommitかstashします。差分スキャンにはgitリポジトリが要ります。バージョン管理のないディレクトリでも、全体スキャンは動きます。

/code-reviewとの違いを早見表で見る

どちらも差分を対象にしますが、見ている観点と指定できる引数が異なります。

観点/security-review/code-review
コマンド一覧の表記/security-reviewSkill表記なし/code-reviewSkill表記あり
主な対象/security-reviewインジェクション・認証不備・データ漏出などの脆弱性/code-review正確性のバグ(モデルと効果レベルによっては整理の余地も)
比較対象/security-revieworiginのデフォルトブランチとの差分/code-review現在の差分、またはPR番号・ブランチ・パス指定
指定できる引数/security-review引数なしのコマンド/code-reviewlow〜maxとultraの深度指定、--fix、--comment、PR番号
深いレビュー/security-review深度指定の段階なし/code-reviewultraでクラウド上のマルチエージェントレビュー

/code-reviewは--fixで指摘を適用し、--commentでGitHub PRにコメントを投稿できます。脆弱性の指摘をPRに載せたい、指摘を自動で直したい、という運用では/code-review側の機能を組み合わせることになります。

originリモートが無いと失敗する — ambiguous argumentエラーの原因

/security-reviewはorigin/HEAD(originリモート上でどのブランチがデフォルトかを記録するローカルの参照)との差分でレビュー対象を組み立てます。この参照が無いと、差分を集めるgitコマンドが失敗し、レビューは始まる前に止まります。

Error: Shell command failed for pattern "!`git diff --name-only origin/HEAD...`": [stderr]
fatal: ambiguous argument 'origin/HEAD...': unknown revision or path not in the working tree.

メッセージに出るgitコマンドは固定ではありません。git logや別のgit diffが引用されることもあります。

origin/HEADは、リモートがデフォルトブランチを公開していて、手元のfetch設定がそのブランチを含むときだけ作られます。コミットのあるリモートをフルクローンすれば両方を満たします。参照が無くなる状況は次の3つです。

原因

origin/HEADが作られない3つの状況

  • fetchの範囲が狭い

    シングルブランチクローンやCIのチェックアウトで、デフォルトブランチがfetchの対象に入っていません。

  • リモートのHEADが空振り

    リモート側のHEADが、誰もpushしていないブランチを指したままです。

  • originが無い・未fetch

    originという名前のリモートが存在しない、または一度もfetchしていません。

gitだけで再現する

gitのバージョンは2.50.1(Apple Git)、init.defaultBranchはmainです。一時ディレクトリにorigin役のベアリポジトリを作り、originが無い状態から順に確かめました。検証に使ったのはgitコマンドだけで、claude本体は使っていません。

$ git init -q --bare r.git          # origin役のベアリポジトリ
$ git init -q a && cd a            # remoteの無いリポジトリ
$ git commit -q --allow-empty -m c # 最初のコミット
$ git diff --name-only origin/HEAD...
fatal: ambiguous argument 'origin/HEAD...': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

エラーリファレンスの文面と同じ出力です。次に、空のベアリポジトリをoriginに追加した直後の様子です。

$ git remote add origin ../r.git
$ git fetch origin
$ git remote set-head origin --auto
error: Cannot determine remote HEAD
$ git remote set-head origin main
error: Not a valid ref: refs/remotes/origin/main

リモートが空のうちは、--autoでも名前の明示でも参照を作れません。1回pushしてorigin/mainができると、--autoが通ります。

$ git push -q -u origin HEAD
$ git remote set-head origin --auto
'origin/HEAD' is now created and points to 'main'
$ git diff --name-only origin/HEAD...
$ echo $?
0

差分は空で終了コードは0です。pushしたばかりのブランチはorigin/mainと同じ位置にあるため、分岐するまで変更が見えません。

エラーを解消する3つの手順

状況に応じて、次のいずれかで解消します。

  1. デフォルトブランチが分かっている場合: git remote set-head origin <デフォルトブランチ名>を実行します。ローカルの追跡参照origin/<ブランチ名>が既にあれば、これだけで解決します。無ければgit remote set-branches --add origin <ブランチ名>→git fetch originの順で先にブランチを取得してから、同じコマンドを実行します
  2. ブランチ名を指定したくない場合: git fetch originのあとにgit remote set-head origin --autoを実行します。リモートに問い合わせてデフォルトブランチを自動判定します。リモートがデフォルトブランチを広告していないとCannot determine remote HEADで失敗するので、手順1のように名前を明示します。クローンがそのブランチをfetchしていないとNot a valid refで失敗するため、fetch範囲を広げてから再試行します
  3. originリモート自体が無い場合: git remote add origin <URL>でリモートを追加してからfetchします。リモートが空なら、先にgit push -u origin HEADで自分のブランチをpushし、そのブランチ名で手順1のコマンドを実行します

いずれの場合も、参照を作り直したあとに/security-reviewを再実行します。

シングルブランチクローンでも同じ流れを試しました。先にaでdevelopブランチを作ってpushします。リモートのHEADはmainのままで、クローンはdevelopだけをfetchした状態です。

$ git switch -q -c develop
$ echo x > develop.txt && git add develop.txt && git commit -q -m develop
$ git push -q origin develop
$ cd .. && git clone -q --single-branch --branch develop r.git s && cd s
$ git rev-parse --abbrev-ref origin/HEAD
origin/HEAD
fatal: ambiguous argument 'origin/HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
$ git remote set-head origin --auto
error: Not a valid ref: refs/remotes/origin/main
$ git branch -r
  origin/develop

リモートのデフォルトはmainと分かっているのに、手元にorigin/mainが無いため--autoが止まります。この状態は手順2の最後の分岐に当たります。mainを取得すれば先へ進めます。

$ git remote set-branches --add origin main
$ git fetch -q origin
$ git remote set-head origin --auto
'origin/HEAD' is unchanged and points to 'main'

fetchした時点でorigin/HEADが作られていたため、続く--autoは変更なしと答えています。

比較先を変えたいときに起きること

/security-reviewは引数なしのコマンドです。エラー文にあるとおり、差分はorigin/HEAD...の形で集められます。比較の基準は、手元のorigin/HEADが指すブランチです。

上のgitの検証環境で、aに戻り、developからさらにfeatureを切って、基準を動かしてみました。

$ cd ../a
$ git switch -q -c feature
$ echo x > feature.txt && git add feature.txt && git commit -q -m feature
$ git remote set-head origin --auto
'origin/HEAD' is unchanged and points to 'main'
$ git diff --name-only origin/HEAD...    # 基準は origin/main
develop.txt
feature.txt
$ git remote set-head origin develop
$ git diff --name-only origin/HEAD...    # 基準は origin/develop
feature.txt

基準がmainのままだと、developで入った変更までfeatureの差分に混ざります。

別の枝から切ったブランチでは、PRの実際の比較先と手元のorigin/HEADがずれます。stacked PRがその典型です。git remote set-headで参照を付け替えれば集まる差分は変わります。ただしこの操作はローカルの参照を書き換えるだけです。ほかのコマンドのorigin/HEADの見え方も変わるため、終わったら元のブランチに戻す運用になります。

差分収集が別のエラーで止まるとき

差分を集めるgitコマンドは、冒頭で触れた動的コンテキスト注入で実行されているようです。この仕組みで失敗するのはambiguous argumentだけではありません。注入されたコマンドの失敗は、スキル呼び出し全体を中断させます。

  • Shell command permission check failed for pattern "...": コマンドの権限チェックがallowを返さなかったときのエラーです。注入中は確認ダイアログが出ないため、allowにならないコマンド(deny、ask、どの規則にも当たらないもの)は中断します。allowed-toolsで事前許可する方法はありますが、denyとaskの規則はallowed-toolsより優先されます。auto modeでは、承認が要るコマンドでも中断せず、Claudeが先に実行する指示つきでスキルが読み込まれます。ただしagentを指定したフォークスキルや、注入コマンドを走らせるシェルツールが無いセッションでは、auto modeでも中断します
  • ... requires bash ... but Git Bash was not found: WindowsでGit Bashが無いときに出ます。メッセージはSkill <name> requires bashで始まります。Git for Windowsを入れるか、シェルの指定を確認します
  • 終了コード: 既定のbashでは、0以外の終了コードはすべて失敗です。grepやgit diffなど検索・比較系のコマンドだけは、終了コード1を通常の結果として扱う例外があります。この例外のコマンドでも、終了コード2以上は失敗です

v2.1.70前後の変遷

公式changelogにある/security-reviewの変更は次の2件です。

バージョン公開日変更内容
v2.1.70公開日2026年3月6日変更内容古いgitでunknown option merge-baseエラーが出て失敗する不具合を修正
v2.1.108公開日2026年4月14日変更内容/init・/reviewと並んで/security-reviewをSkillツール経由でモデル自身が発見・呼び出せるように改善

v2.1.108の変更は、Claudeが/security-reviewのような組み込みコマンドをツール呼び出しとして見つけて実行できるようになった、という内容です。

まとめ

比較の基準を決めるのは、手元のorigin/HEADです。stacked PRのようにPRの比較先とずれるブランチでは、実行前にorigin/HEADの指す先を確かめます。

この記事を共有:XはてブLinkedIn