← 一覧に戻る

Permission自動承認 調査・対策計画

2026年4月5日 00:39 更新
MD から自動変換されたページです。内容について質問があれば右下の ? ボタンからどうぞ。

ステータス: 調査完了・実装待ち

問題

秘書セッションが作業セッション(tmux)のpermissionダイアログを承認する運用において:

  1. .claude/ 配下のファイル(scripts/, skills/, memory/ 等)を編集するたびにpermissionダイアログが出る
  2. 秘書がtmux send-keysで承認しても、次の編集で再びダイアログが出て止まる
  3. option 2 を選んでもパスカテゴリが変わると再度聞かれる(scripts/ → skills/ → memory/ は別扱い)
  4. 結果、Codexレビュー修正のような複数ファイル編集タスクが何時間も止まる
  5. tmux send-keys の入力が効かないケースがある

根本原因分析

原因1: .claude/ は bypassPermissions でも意図的に保護される

Claude Code は .claude/, .git/, .vscode/, .idea/, .husky/ を「保護ディレクトリ」として扱い、bypassPermissions モードでも書き込み時に確認ダイアログを表示する。これは Claude が自分のhooksやsettingsを改ざんして権限を昇格させることを防ぐ セキュリティ設計。

例外(ダイアログが出ない):

ダイアログが出る:

原因2: セッション内の自己編集許可はパスカテゴリごと

「Yes, and allow Claude to edit its own settings for this session」を選択すると、そのセッション内で 同じカテゴリ のファイルへの編集が許可される。しかし scripts/rules/docs/ はそれぞれ別カテゴリとして扱われるため、カテゴリが変わるたびに再度ダイアログが出る。

原因3: tmux send-keys の空振り

Claude Code のTUI(テキストベースUI)は通常のシェルと異なり、Enter だけではダイアログの選択が確定しない場合がある。特に:

原因4: 承認後の検証がない

秘書が tmux send-keys で承認を送った後、承認が通ったかの確認次のダイアログが出ていないかの確認 をしていない。空振りに気づけない。


対策(3層防御)

対策1: PermissionRequest フックによる自動承認(最優先)

PermissionRequest フックで .claude/ 配下の安全なパスへの編集を自動承認する。これはダイアログが表示される前に判定が行われるため、秘書の介入が不要になる。

新規スクリプト: ~/.claude/scripts/auto-approve-claude-dir.sh

#!/bin/bash
# auto-approve-claude-dir.sh — .claude/ 配下の安全なパスを自動承認
# PermissionRequest フックから呼ばれる
#
# 安全方針:
#   - settings.json は自動承認しない(権限昇格リスク)
#   - hooks 関連は自動承認しない
#   - scripts/, rules/, docs/, memory/, backups/ のみ自動承認

INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)

# ファイルパスが取得できない場合は何もしない(ダイアログをそのまま表示)
[ -z "$FILE_PATH" ] && exit 0

# .claude/ 配下かどうか判定
case "$FILE_PATH" in
  */.claude/scripts/*|*/.claude/rules/*|*/.claude/docs/*|*/.claude/backups/*|*/.claude/projects/*/memory/*|*/.claude/projects/*/MEMORY.md)
    # 安全なパス → 自動承認
    echo '{"hookSpecificOutput":{"hookEventName":"PermissionRequest","decision":{"behavior":"allow"}}}'
    ;;
  */.claude/settings.json|*/.claude/settings.local.json|*/.claude/hooks*.json)
    # 危険なパス → 自動承認しない(ダイアログを表示)
    exit 0
    ;;
  *)
    # .claude/ 以外 → このフックでは判定しない
    exit 0
    ;;
esac

settings.json の変更:

"PermissionRequest": [
  {
    "matcher": "Edit|Write",
    "hooks": [
      {
        "type": "command",
        "command": "~/.claude/scripts/auto-approve-claude-dir.sh"
      },
      {
        "type": "command",
        "command": "~/.claude/scripts/notify-secretary-permission.sh"
      }
    ]
  }
]

フックの実行順序:

  1. auto-approve-claude-dir.sh が先に実行される
  2. 自動承認対象 → JSON を stdout に出力 → ダイアログ表示されず、通知も不要
  3. 自動承認対象外 → exit 0(何も出力しない)→ 次のフック notify-secretary-permission.sh が実行 → 秘書に通知

期待効果: .claude/scripts/, .claude/rules/, .claude/docs/ 等の日常的な編集でダイアログが出なくなる。Codexレビュー修正時の大半のブロックが解消。

対策2: permissions.allow にパス指定を追加(保険)

GitHub issues では「効かない」という報告があるが、公式ドキュメントには Edit(~/.claude/**) 形式のパス指定が記載されている。対策1との併用で防御の深さを確保する。

"permissions": {
  "allow": [
    "Edit(~/.claude/scripts/**)",
    "Edit(~/.claude/rules/**)",
    "Edit(~/.claude/docs/**)",
    "Edit(~/.claude/backups/**)",
    "Write(~/.claude/scripts/**)",
    "Write(~/.claude/rules/**)",
    "Write(~/.claude/docs/**)",
    "Write(~/.claude/backups/**)",
    // ... 既存の allow ルール
  ]
}

対策3: 秘書の承認検証フロー改善(フォールバック)

対策1・2で大半は解消されるが、settings.json 等の意図的に保護されたファイルは引き続きダイアログが出る。その場合の秘書フローを改善する。

改善点: 「送って終わり」→「送って確認してループ」

1. tmux send-keys で承認キーを送信
2. sleep 0.5
3. capture-pane でダイアログが消えたか確認
4. まだダイアログが残っている場合:
   a. Escape → Enter の2段階送信を試行
   b. sleep 0.5
   c. 再度 capture-pane で確認
5. ダイアログが消えた場合:
   a. sleep 1.0(次のダイアログ出現を待つ)
   b. capture-pane で新しいダイアログが出ていないか確認
   c. 出ていれば → ステップ1に戻る(連続承認ループ)
   d. 出ていなければ → 完了
6. 最大リトライ回数: 10回(無限ループ防止)
7. 全試行をログに記録

検証の grep パターン:

# ダイアログ検出
grep -qiE '(Do you want to|Allow this|Esc to cancel|Allow .* Deny|Yes .* No|allow Claude to edit)'

# 作業再開の確認(ダイアログ消失 + Claude が動いている)
grep -qiE '(esc to interrupt|⠋|⠙|⠹|⠸|⠼|⠴|⠦|⠧|⠇|⠏)'

安全策

自動承認しないパス(明示的ブロックリスト)

パス 理由
settings.json 権限設定そのもの。自動承認すると権限昇格が可能
settings.local.json 同上
hooks*.json フック設定。改ざんで任意コマンド実行が可能
.credentials.json 認証情報

監査ログ

ロールバック手順

対策1(フック)に問題がある場合:

  1. settings.json から auto-approve-claude-dir.sh のフックエントリを削除
  2. セッション再起動(フック設定はセッション起動時に読み込まれるため)

tmux send-keys の空振り対策

根本原因

Claude Code のTUIは、ダイアログの選択肢にフォーカスがある状態で特定のキー入力を期待する。send-keys '1'send-keys '2' が効かないのは:

  1. TUIのフォーカスが選択肢UI上にない
  2. 数字キーが「入力フィールド」に吸われている
  3. ダイアログのレンダリング完了前に入力が到達

対策

# 推奨: Enter で最初の選択肢を選ぶ(数字キーより確実)
tmux send-keys -t "$SESSION:$WINDOW" Enter

# Enter が効かない場合のフォールバック
sleep 0.3
tmux send-keys -t "$SESSION:$WINDOW" Escape
sleep 0.3
tmux send-keys -t "$SESSION:$WINDOW" Enter

重要: 送信後は必ず capture-pane で結果を確認する。


実装順序

  1. auto-approve-claude-dir.sh を作成(対策1)
  2. settings.json にフックを追加(対策1)
  3. permissions.allow にパス指定を追加(対策2)
  4. テスト: .claude/scripts/ 内のファイルを Edit で変更し、ダイアログが出ないことを確認
  5. 秘書の承認フローを更新(対策3)— 既存の運用ドキュメントに検証ループを追記
  6. ADR-013 として記録

参考リンク


Codexレビュー結果(2026-04-05)

Critical 指摘(全て対応済み)

  1. パストラバーサル脆弱性FILE_PATH を生文字列で case 判定していた。/.claude/scripts/../settings.json でdenyリストをバイパスできる。→ realpath -m で正規化、シンボリックリンク拒否を追加
  2. .claude/scripts/* が広すぎる — フックスクリプト自体を改ざんされると権限判定を乗っ取れる。→ scripts/ を自動承認対象から除外。docs/, backups/, logs/, memory/ のみに限定
  3. フック並列実行レースauto-approvenotify-secretary が同時に走る可能性。→ 1本のスクリプトに統合(auto-approve-claude-dir.sh が判定+通知の両方を担当)
  4. 秘書の対象照合なし — ダイアログの有無だけ見て、何のダイアログかを確認していない。→ 秘書フローに tool_name + file_path 照合を追加(対策3に反映)

Warning 指摘(設計判断として記録)

修正後の自動承認範囲

パス 判定 理由
docs/, backups/ 自動承認 ドキュメント。実行境界に影響しない
logs/ 自動承認 ログ。実害なし
projects/*/memory/ 自動承認 日常運用頻度を考慮
commands/, agents/, skills/ 自動承認 Claude Code が元々例外扱い
scripts/ 手動承認 フックスクリプト改ざんリスク
rules/ 手動承認 プロンプト注入リスク
settings*.json 手動承認 権限昇格リスク
hooks*.json 手動承認 任意コマンド実行リスク

設計変更: 統合スクリプト

旧設計(2本立て):

PermissionRequest → auto-approve-claude-dir.sh → notify-secretary-permission.sh

新設計(1本統合):

PermissionRequest → auto-approve-claude-dir.sh(判定 + 通知を1本で)

notify-secretary-permission.sh は settings.json から削除し、auto-approve-claude-dir.sh に置き換える。

settings.json 変更案

"PermissionRequest": [
  {
    "matcher": "Edit|Write",
    "hooks": [
      {
        "type": "command",
        "command": "~/.claude/scripts/auto-approve-claude-dir.sh"
      }
    ]
  }
]

notify-secretary-permission.sh のフックエントリは削除(統合されたため不要)。

秘書の承認検証フロー(対策3・改訂版)

Codex指摘を反映: 「送って確認」だけでなく「対象照合」も実施。

1. PermissionRequest 通知を受信
2. 通知メッセージから session_id, tool_name, file_path を抽出
3. capture-pane でダイアログ内容を取得
4. ダイアログ内の tool_name と file_path が通知と一致するか照合
   → 一致しない場合: ログに記録して承認しない(誤承認防止)
5. tmux send-keys で承認キー(Enter)を送信
6. sleep 0.5
7. capture-pane でダイアログが消えたか確認
8. まだダイアログが残っている場合:
   a. Escape → sleep 0.3 → Enter の2段階送信
   b. sleep 0.5 → 再度 capture-pane
9. ダイアログが消えた場合:
   a. sleep 1.0(次のダイアログ出現を待つ)
   b. capture-pane で新しいダイアログチェック
   c. 出ていれば → ステップ3に戻る(連続承認ループ)
   d. 出ていなければ → 完了
10. 最大リトライ: 10回(無限ループ防止)
11. 全試行をログに記録

実装順序(改訂版)

  1. auto-approve-claude-dir.sh 作成(Codex指摘反映済み)
  2. settings.json の PermissionRequest フックを更新(統合版に差し替え)
  3. 旧 notify-secretary-permission.sh をバックアップ(削除はしない)
  4. テスト: .claude/docs/ 内のファイルを Edit → ダイアログ出ないことを確認
  5. テスト: .claude/scripts/ 内のファイルを Edit → ダイアログ出る+秘書に通知されることを確認
  6. 秘書の承認フローを改訂版に更新
  7. ADR-013 として記録
  8. セッション再起動して動作確認
📝 質問モード — テキストを選択してね
✓ 質問を送信しました