Skip to content

feat(hooks-pre-tool-validate): secret-detection preset 追加 (順位 146) - #201

Merged
aloekun merged 1 commit into
masterfrom
feat/secret-detection-hook
Jun 10, 2026
Merged

feat(hooks-pre-tool-validate): secret-detection preset 追加 (順位 146)#201
aloekun merged 1 commit into
masterfrom
feat/secret-detection-hook

Conversation

@aloekun

@aloekun aloekun commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • 順位 146 (Tier 1 security-critical): secret-detection preset を hooks-pre-tool-validate に追加
  • AWS Access/Secret Key、OpenAI sk- 系、GitHub PAT (ghp_/github_pat_)、GitHub OAuth (gho_/ghs_/ghu_/ghr_)、Anthropic sk-ant- の 6 種類の hardcoded secret pattern を regex 検出
  • Bash command + Edit/Write content (new_string + content、old_string は除外して secret 削除操作を allow) の両方をスキャン
  • default_preset_names() に含めて Tier 1 default-on (漏洩の非対称性 = 1 度漏れたら手遅れ、jj-message-required の opt-in とは別判断)
  • ~/.claude/rules/common/security.md § Secret Management の機械強制層 (feedback_pipeline_over_rules.md 適用)

Changes

  • src/hooks-pre-tool-validate/src/main.rs: preset_secret_detection() + SECRET_DETECTION_MSG 定数 + 4 helper 関数 (resolve_edit_file_path, check_protected_file, check_secret_in_content, check_todo_staleness_for_edit) で handle_write_edit_tool を 50 行制限内に分割 + 18 新規 tests
  • .claude/hooks-config.toml: blocked_patternssecret-detection 追加 + コメント section
  • docs/todo9.md: 順位 146 entry retire
  • docs/todo-summary.md: 146 行削除 + 199-202 行追加 (prior session の post-merge-feedback registrations)
  • docs/todo10.md: 199-202 entries の詳細記載 (prior session 由来)

既存設計との関係

  • 順位 144 (jj-message-required) と同型実装パターン、BlockedPattern.exception 機構を再利用 (Rust regex は negative lookahead 非対応、PR test(hooks): UTF-8 boundary + aggregation cap 拡充 (順位 125 + 57 + 91) #171 で導入された 2 段判定)
  • Anthropic 系 prefix は OpenAI pattern の exception で除外 + 専用 pattern で別途検出 (defense in depth)
  • AWS Secret Key は env-var-assignment 形式 (aws_secret_access_key = "...") に限定して FP 軽減

Test plan

  • cargo test -p hooks-pre-tool-validate: 202/202 pass (新規 18 secret-detection tests 含む、回帰なし)
  • dogfood: pnpm build:hooks-pre-tool-validate.claude/ exe deploy → AI 自身の AWS-Access-Key 形式投入を PreToolUse 層で実 block 確認
  • 通常コマンド (ls -la) / Edit (regular code) は exit 0 で allow 確認
  • takt pre-push-review: simplicity-review + security-review 両 APPROVE (1 iteration、9 分)

pre-push-review 非ブロッキング指摘 (follow-up 候補)

  • NB-1: OpenAI threshold 40+ (設計 doc は 20+ と記載) の根拠 inline comment 不在 → Bundle Z #B-α (// 非 doc コメント禁止 lint) との衝突あり、別途 function-level doc 追記で対応検討
  • NB-2: ghu_ / ghr_ token type の dedicated test 欠落 (gho_/ghs_ と同 regex alternation 内のため低リスク、test matrix gap)

同梱: 順位 199-202 (queue 登録のみ)

prior session で post-merge-feedback skill が PR #200 T2-1/T3-1/T3-2/T3-3 採用判定後に prepared した todo entries (実装はせず queue 登録のみ)。docs/todo-summary.md が同ファイル内で 199-202 行追加 + 146 行削除を抱え、jj 非対話 split (path 単位) で分離不能だったため bundle (詳細は commit description 参照)。

関連

Summary by CodeRabbit

リリースノート

  • 新機能

    • AWS/OpenAI/GitHub トークンなど、ハードコードされたシークレットの検出・ブロック機能を追加しました。デフォルトで有効化されます。
  • ドキュメント

    • マルチバイト文字テストの標準要件、Rust の文字列インデックスガイドライン、テスト機構の分離方法に関する文書を更新しました。

- AWS Access/Secret Key, OpenAI sk-, GitHub PAT/OAuth, Anthropic sk-ant- の
  6 種類 hardcoded secret pattern を regex 検出
- Bash command + Edit/Write content の両方をスキャン (handle_write_edit_tool
  に secret scan 統合、old_string は除外して secret 削除操作を allow)
- default_preset_names に含めて Tier 1 security-critical default-on
  (漏洩の非対称性 = 1 度漏れたら手遅れ、jj-message-required の opt-in とは別判断)
- handle_write_edit_tool を 4 helper 関数に分割 (関数長 50 行制限対応)
- 既存 BlockedPattern.exception 機構を再利用、Anthropic sk-ant- を OpenAI sk-
  pattern の exception で除外 (Rust regex negative lookahead 代替、順位 144 で導入)
- ~/.claude/rules/common/security.md § Secret Management の機械強制層

cargo test 202/202 pass (新規 secret-detection 18 tests 追加、回帰なし)
dogfood: PreToolUse 層で AI 自身の echo AKIA... 投入を実 block 確認

同梱 (queue 登録のみ、本 PR では実装せず):
- 順位 199-202: PR #200 post-merge-feedback T2-1/T3-1/T3-2/T3-3 採用 entries
  prior session 由来の registration、todo10.md / todo-summary.md に entries 追記

bundle 理由: docs/todo-summary.md が同ファイル内で 199-202 行追加 + 146 行削除を
抱え、jj 非対話 split (path 単位) で分離不能 (partial-file split が必要なため)。
無理に分けると surgery コスト > 収益、reviewer から見ても一貫性なし。
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

PR #201 は、Bash コマンド検証に加えて Write/Edit/Replace ツール入力中のハードコードされたシークレット(AWS/OpenAI/GitHub/Anthropic トークン等)を正規表現で検出・ブロックする「secret-detection」プリセットを実装し、デフォルト有効化、設定ファイルに登録、テスト追加し、完了タスクを記録して、後続のマルチバイト文字テスト標準化タスクを計画します。

Changes

Secret Detection Preset Implementation

Layer / File(s) Summary
Secret Detection Preset Definition and Wiring
src/hooks-pre-tool-validate/src/main.rs
preset_secret_detection() 関数で AWS/OpenAI/GitHub/Anthropic トークンの正規表現パターンと検出メッセージ定数を定義し、default_preset_names() および resolve_preset_or_custom() に統合することで、設定ファイル未指定でもデフォルト有効化。
Write/Edit Validation Logic Refactoring
src/hooks-pre-tool-validate/src/main.rs
collect_text_for_secret_scan()is_secret_detection_enabled() ヘルパーを追加し、Write/Edit/Replace の検証フロー(保護ファイル判定 → シークレット検出 → todo staleness 判定)を補助関数群に分割・整理。old_string をスキャン対象から除外して削除操作をブロック対象外に。
Secret Detection Test Coverage
src/hooks-pre-tool-validate/src/main.rs
シークレット各種パターン検出、短いフィクスチャ値の許可、old_string 除外による削除非ブロック、他プリセットとの非干渉を検証するテストスイート追加。
Configuration and Settings
.claude/hooks-config.toml
pre_tool_validate プリセット一覧に secret-detection の説明ブロック(目的、検出対象、実行形態)を追記し、blocked_patterns"secret-detection" を追加して実行可能化。
Documentation: Task Completion and Follow-up Planning
docs/todo-summary.md, docs/todo9.md, docs/todo10.md
todo-summary.md から順位 146(Secret detection)を削除。todo9.md から詳細タスクブロックを削除。todo10.md にマルチバイト文字 string window テスト標準化、Rust インデックス運用ガイド、ADR-007 LazyLock<Regex> guideline 追記、testing.md multi-path fixture isolation セクション追記の4つの後続タスク(順位 199-202)を新規追加。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • aloekun/claude-code-hook-test#27: どちらのPRも src/hooks-pre-tool-validate/src/main.rspre_tool_validate 側で BlockedPattern プリセット(secret-detection vs gh-pr-merge-guard)を追加し、.claude/hooks-config.tomlpre_tool_validate.blocked_patterns に統合するため、同じプリセット拡張パターンでコード関連度が高い。
  • aloekun/claude-code-hook-test#166: どちらも hooks-pre-tool-validate に新しいプリセットを追加し、hooks-config.tomlblocked_patterns/preset 解決(build_blocked_patterns 等)に統合するため、同じ統合ポイントをコードレベルで拡張する関連性がある。
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed プルリクエストのタイトルは、主要な変更である「secret-detection プリセットの追加」を明確かつ簡潔に要約しており、チェンジセット全体の目的と一致している。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/hooks-pre-tool-validate/src/main.rs (1)

1327-1341: ⚡ Quick win

ghu_ / ghr_ の回帰テストも追加しておくと契約が固まります。

Line [517] の正規表現は gho|ghs|ghu|ghr を対象にしていますが、追加テストは gho_ghs_ のみです。ghu_ / ghr_ も1本ずつ置いておくと、将来の regex 変更での取りこぼしを防げます。

追加テスト例
     #[test]
     fn secret_detection_blocks_github_server_token() {
         assert!(is_blocked_with(
             "let token = \"ghs_abcdefghijklmnopqrstuvwxyz0123456789\";",
             SECRET_DETECT
         ));
     }

+    #[test]
+    fn secret_detection_blocks_github_user_to_server_token() {
+        assert!(is_blocked_with(
+            "let token = \"ghu_abcdefghijklmnopqrstuvwxyz0123456789\";",
+            SECRET_DETECT
+        ));
+    }
+
+    #[test]
+    fn secret_detection_blocks_github_refresh_token() {
+        assert!(is_blocked_with(
+            "let token = \"ghr_abcdefghijklmnopqrstuvwxyz0123456789\";",
+            SECRET_DETECT
+        ));
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks-pre-tool-validate/src/main.rs` around lines 1327 - 1341, Add two
more unit tests to cover GitHub token prefixes `ghu_` and `ghr_` so the
secret-detection regex (which targets `gho|ghs|ghu|ghr` around line 517) is
fully exercised; duplicate the pattern used in
secret_detection_blocks_github_oauth_token and
secret_detection_blocks_github_server_token by creating tests that call
is_blocked_with with strings containing "let token =
\"ghu_abcdefghijklmnopqrstuvwxyz0123456789\";" and "let token =
\"ghr_abcdefghijklmnopqrstuvwxyz0123456789\";" using SECRET_DETECT to ensure
those cases are blocked.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/hooks-pre-tool-validate/src/main.rs`:
- Around line 533-537: Update the SECRET_DETECTION_MSG text so it no longer
suggests editing `.env*` as an automated fix (which conflicts with
check_protected_file blocking `.env*` edits); instead explicitly instruct that
remediation is manual and recommend moving secrets to environment variables
(std::env::var or process.env), a secret manager (1Password/Doppler/AWS/GH
Secrets), or a local .env only for dev with .gitignore, and instruct test
fixtures to use clearly invalid short tokens like "AKIATEST" to avoid regex
matches; change the message in main.rs where SECRET_DETECTION_MSG is defined and
ensure wording references check_protected_file to clarify the block.

---

Nitpick comments:
In `@src/hooks-pre-tool-validate/src/main.rs`:
- Around line 1327-1341: Add two more unit tests to cover GitHub token prefixes
`ghu_` and `ghr_` so the secret-detection regex (which targets `gho|ghs|ghu|ghr`
around line 517) is fully exercised; duplicate the pattern used in
secret_detection_blocks_github_oauth_token and
secret_detection_blocks_github_server_token by creating tests that call
is_blocked_with with strings containing "let token =
\"ghu_abcdefghijklmnopqrstuvwxyz0123456789\";" and "let token =
\"ghr_abcdefghijklmnopqrstuvwxyz0123456789\";" using SECRET_DETECT to ensure
those cases are blocked.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d9f3d7ed-cf52-46d7-bc14-bf1d663b4f5d

📥 Commits

Reviewing files that changed from the base of the PR and between 90306c3 and e993bdd.

📒 Files selected for processing (5)
  • .claude/hooks-config.toml
  • docs/todo-summary.md
  • docs/todo10.md
  • docs/todo9.md
  • src/hooks-pre-tool-validate/src/main.rs
💤 Files with no reviewable changes (1)
  • docs/todo9.md

Comment on lines +533 to +537
**対応方法:**
- 環境変数に移管: Rust なら `std::env::var("API_KEY")`、Node.js なら `process.env.API_KEY`
- Secret manager (1Password / Doppler / AWS Secrets Manager / GitHub Actions Secrets 等) を使用
- `.env` ファイル + `.gitignore` で local-only 管理 (本番は別途)
- test fixture でも、regex に match する形式 (16 chars 以上の AKIA... 等) は避け、`AKIATEST` 等の明らかに無効な短い形を使う

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

SECRET_DETECTION_MSG の案内が実行可能な対処とズレています。

Line [536] で .env 管理を案内していますが、同ファイルの check_protected_file により .env* 編集はブロックされます。Claude 経由での対処として誤解を招くため、手動対応である旨を明記した方が安全です。

修正例
 - `.env` ファイル + `.gitignore` で local-only 管理 (本番は別途)
+ - `.env` ファイル + `.gitignore` で local-only 管理 (本番は別途)
+   ※ `.env*` は保護対象のため、Claude ではなくユーザー側で編集してください
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks-pre-tool-validate/src/main.rs` around lines 533 - 537, Update the
SECRET_DETECTION_MSG text so it no longer suggests editing `.env*` as an
automated fix (which conflicts with check_protected_file blocking `.env*`
edits); instead explicitly instruct that remediation is manual and recommend
moving secrets to environment variables (std::env::var or process.env), a secret
manager (1Password/Doppler/AWS/GH Secrets), or a local .env only for dev with
.gitignore, and instruct test fixtures to use clearly invalid short tokens like
"AKIATEST" to avoid regex matches; change the message in main.rs where
SECRET_DETECTION_MSG is defined and ensure wording references
check_protected_file to clarify the block.

@aloekun
aloekun merged commit d5ca4f5 into master Jun 10, 2026
1 check passed
@aloekun
aloekun deleted the feat/secret-detection-hook branch June 10, 2026 05:26
aloekun added a commit that referenced this pull request Jun 10, 2026
…47 + 151) (#202)

* docs(todo): 順位 203/204/205 追加 (PR #201 post-merge-feedback 採用)

* feat(hooks-comment-lint-rust): file_length lint 追加 (順位 147、touch-trigger ratchet)

* feat(cli-push-runner): pr_size_check stage 追加 (順位 151、ADR-039 試験運用)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant