From 322c72b6cea36364a6f25af74c97efd204a995a0 Mon Sep 17 00:00:00 2001 From: TTMK7777 Date: Fri, 31 Jul 2026 18:18:22 +0900 Subject: [PATCH] =?UTF-8?q?docs(CLAUDE.md):=20=E6=A4=9C=E5=87=BA=E3=83=AB?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E8=BF=BD=E5=8A=A0=E6=99=82=E3=81=AE=E5=BF=85?= =?UTF-8?q?=E9=A0=88=E6=89=8B=E9=A0=86=E3=82=92=E6=98=8E=E6=96=87=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit このリポジトリ固有の最重要ルールとして「自作の合成フィクスチャだけで 動くと判断しない」を proof として明記する。 背景: 合成フィクスチャで誤検知ゼロだったルール群が、実コード 10 リポ 1015 ファイルでは 121 件中の真の指摘が約 2 件(誤検知率 98%)だった。 ミューテーションテストに合格していても、ルールが実世界で妥当かは 一切示さない。この失敗を手順として固定する。 追記内容: - 単体テストは発火例と非発火例の両方 + 公開経路を通す(配線漏れ検出) - 実コーパス計測で誤検知率を数値化し、NET-NEW を全件目視する - 既存ゲート(CodeQL/Dependabot/シークレットスキャナ)との重複を先に測る - 誤検知を生みやすい既知の型 5 つ(SQLキーワードは英単語 / 同名メソッド / 定数実行 / 語の出現≠使用 / モジュール横断は判定不能) - 意図的に脆弱なテストには ignore-file を置く 検証: pytest 153 件パス(ドキュメントのみの変更でコード影響なし) --- CLAUDE.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) 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 が自分のテストで落ちる。