Claude Code の security-guidance フックは何に反応したか(31件のうち、ほとんどが誤反応だった)
- Claude Code
- セキュリティ
Claude Code の公式プラグイン security-guidance を入れています。Claude がファイルを書いたとき、危なそうなコード(eval( や innerHTML = など)が含まれていると、Claude に警告を出してくれるプラグインです。
ありがたい反面、どう見ても安全なコードにも反応します。実際にどれくらい反応していたのかを、会話ログから数えてみました。
環境:Windows 10 / Claude Code 2.1.302 / security-guidance 2.0.14
仕組み
プラグインのソースの冒頭に、仕組みが書いてあります。大きく2つの層があります。
- パターン規則:ファイルを書くたびに、正規表現や文字列で危なそうな書き方を探し、見つかったら Claude に警告を渡す
- 終了時のレビュー:Claude が作業を終えるときに、その間の変更(git diff)を AI に読ませて脆弱性を探す
この記事で扱うのは 1 のパターン規則です。規則は patterns.py に並んでいて、eval(、innerHTML =、child_process.exec、pickle、yaml.load など20種類以上あります。
会話ログから31件を集めた
Claude Code の会話ログ(~/.claude/projects/<プロジェクト>/<セッション>.jsonl)から、フックが出した「Security Warning」を集めました。期間は 2026年9月17日〜10月13日で、31件ありました。
| 警告 | 件数 | 実際に書いていたもの |
|---|---|---|
innerHTML で XSS | 16 | 固定の SVG アイコン、テスト用の固定 HTML、エスケープ済みの値 |
eval() は危険 | 9 | Playwright の page.$eval(...) / page.$$eval(...) など |
child_process.exec でコマンドインジェクション | 5 | 正規表現の pattern.exec(text)、SQLite の db.exec(...) |
pickle で任意コード実行 | 1 | 信頼できる配布元のモデルを読み込むコード |
ファイルの種類は、.js が17件、.ts と .mjs が5件と4件、.py が4件でした。
innerHTML は、中身が固定の文字列だったり、値をエスケープ済みだったりで、外からの入力が入るものはほぼありませんでした。eval と exec は、名前が似ているだけで別物です。31件のうち、本当に直すべきだったものは見当たりませんでした。
Claude は警告を避けるためにコードを書き換えていた
困ったのは、警告そのものより、警告を受けた Claude の動きでした。警告の直後に Claude が何をしたかを見ると、こうなっていました。
| Claude の対応 | 回数 | 例 |
|---|---|---|
| 警告が出ない書き方に書き換えた | 約13回 | pattern.exec(text) → text.match(pattern)、page.$eval → evaluate を避けて getAttribute、innerHTML → createElement |
| 安全だと説明して、同じ編集をもう一度送った | 5回 | 「値はすべて esc() 済みなので同じ編集を再実行します」 |
| 警告が出る行を避けて、編集を分けた | 1回 | 「innerHTML の行を含むので、その行を避けて編集を分けます」 |
innerHTML を DOM の組み立てに変えるのは、悪いことではありません。でも、正規表現の .exec を .match に変えるのは、セキュリティとは関係なく、フックに引っかからないためだけの書き換え です。差分が増えて、レビューする側の手間も増えます。
最後の「編集を分ける」は、警告をかわしただけで中身は同じです。警告の意味がなくなっています。
ちなみに、ログ時点の版では、警告が出ると最初の1回は書き込み自体が止められていたようです。Claude のメッセージに「blocked」「再実行します」が何度も出てきます。
最新版(2.0.14)では一部が直っていた
プラグインは 2026年10月16日に 2.0.14 に更新されていました。ログに残っていたコードを、最新版の規則に当てて試しました。
| コード | ログ時点 | 2.0.14 |
|---|---|---|
pattern.exec(text) | 反応 | 反応しない |
/re/.exec(req.url()) | 反応 | 反応しない |
db.exec(readFileSync(...)) | 反応 | 反応しない |
model.eval()(PyTorch) | — | 反応しない |
page.$eval('#id', ...) | 反応 | まだ反応する |
page.$$eval('.cell', ...) | 反応 | まだ反応する |
固定 SVG の c.innerHTML = '<svg ...>' | 反応 | まだ反応する |
規則のコメントを読むと、.exec( や .eval( のように 直前に . があるもの(メソッド呼び出し)は除外する ように直されていました。ただ、Playwright の $eval は直前が $ なので、まだ引っかかります。
この記事を書く途中でも、反応しました。上の表を確かめるために、page.$eval(...) という文字列を含む Python のテスト用スクリプトを書いたら、そのスクリプト自体に eval() の警告が出ました。
付き合い方
規則ごとには止められない
プラグインのソースには、設定用の環境変数が書いてあります。
| 環境変数 | 効果 |
|---|---|
ENABLE_PATTERN_RULES=0 | パターン規則を全部止める |
ENABLE_CODE_SECURITY_REVIEW=0 | 終了時の AI レビューを止める |
SECURITY_GUIDANCE_DISABLE=1 | プラグインを丸ごと止める |
組み込みの規則を1つだけ止める方法はありません(ソースのコメントにも「Built-in patterns cannot be disabled」とあります)。$eval だけ黙らせる、ということはできません。
全部止めるほどではないので、プラグインは入れたままにしています。本当に危ないコードを書いたときに気づけるほうが大事です。
Claude への指示で、無駄な書き換えを減らす
困るのは誤反応そのものより、それを避けるための書き換えです。そこで、Claude への指示(CLAUDE.md)でこう伝えるのがよさそうです。
- 警告が出たら、まず本当に危ないかを確かめる
- 誤反応なら、コードは書き換えずに、理由を一言添えてそのまま進める
- 警告を避けるためだけに、編集を分けたり書き方を変えたりしない
eval() の警告文にも「安全なら、その旨をコメントに残して続けてよい」と書かれています。誤反応を理由にコードの書き方を曲げる必要はありません。
まとめ
- security-guidance のパターン規則は、文字列や正規表現で反応するので誤反応が出る
- 会話ログの31件は、ほとんどが
innerHTMLの固定文字列と、$eval/.exec(への誤反応だった - Claude は警告を避けるために、セキュリティと関係のない書き換えをしていた
- 2.0.14 で
.exec(などは直ったが、Playwright の$evalにはまだ反応する - 規則は個別に止められないので、「誤反応ならコードを曲げない」と Claude に伝えておく
参考文献
この記事をシェア