diff --git a/CLAUDE.md b/CLAUDE.md index 72d2d83..c6cf279 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,3 +24,28 @@ ## コード規約 - Python: PEP 8, pytest, 型ヒント推奨 - 依存関係: pydantic == 2.13.4(最小依存) + +## 検出ルールを追加・変更するときの必須手順(proof) + +このリポジトリ固有の最重要ルール。**自作の合成フィクスチャだけで「動く」と判断しない。** + +1. **単体テスト** — `python -m pytest tests/ -q` + - 各ルールに「**発火する例**」と「**発火しない例**」の両方を書く。片方だけではトートロジーになる + - 内部関数ではなく公開経路(`scan_file` / `check_file`)を通す。過去に「パターンは定義したが呼んでいない」配線漏れが2件あり、内部関数テストでは検出できない +2. **実コーパス計測** — 実在するリポジトリ群に対して走らせ、**誤検知率を数値で出す** + - 合成フィクスチャは「自分が想定した書き方」しか含まないので、通って当然。ミューテーションテストに合格しても、ルールが実世界で妥当かは**一切示さない** + - 実測例: 合成フィクスチャで誤検知ゼロだったルール群が、実コード 10 リポ 1,015 ファイルでは **121 件中の真の指摘が約 2 件(誤検知率 98%)** だった + - **NET-NEW(既存ゲートが見ていない指摘)を全件目視する。** 件数だけを見ない + - 出力ディレクトリの作成漏れ等で全件 0 になる事故に注意。**「0 件」は「見ていない」を疑う** +3. **既存ゲートとの重複確認** — 導入先に CodeQL / Dependabot / シークレットスキャナが既にある場合、 + それらが出していない指摘が実際に出るかを先に測る。出ないなら、そのルールを足す価値はない + +### 誤検知を生みやすい既知の型(新ルールを書く前に読む) +- SQL キーワードは英単語(`delete` / `update` / `insert`)としてごく普通に現れる → 「SQL 実行文脈」か「文字列が SQL 文で始まる」を必須条件に +- 危険な関数名は同名メソッドを持つ(`model.eval()` / `regex.exec()`)→ 直前が `.`/英数字/引用符なら除外 +- 定数実行は注入経路ではない(`os.system("clear")`)→ 動的構築を伴う場合のみ +- 語の出現はその技術の使用を意味しない(バッジ文字列の "FastAPI")→ インスタンス化を条件に +- **モジュール横断の事実は行単位スキャナでは判定できない。** 絞り込みで解決しない種類は、ルールごと削除する(SEC007 削除の経緯を参照) + +### 意図的に脆弱なコードを含むテスト +`# code-validator: ignore-file` を先頭に置く。これが無いと `--git-diff` の CI が自分のテストで落ちる。