🛡️

Claude Code rm コマンド安全チェック

に公開

概要

Claude Code でファイル削除コマンドを実行する際、意図しない重要なファイルの削除を防ぐため、PreToolUse hook を使用した安全チェック機能を実装しました。

この記事で作成するスクリプトは、以下の機能を持った Bashスクリプト です:

  • 絶対パスでのファイル削除をブロック
  • ホームディレクトリパスでのファイル削除をブロック
  • 複数ファイルの一括チェック機能
  • JSON形式での結果出力でClaude Codeと連携

なぜこれが必要なのか

危険な削除コマンド

Claude Code は非常に強力なツールですが、以下のような危険な削除コマンドを実行してしまう可能性があります:

  • 絶対パス削除: /tmp/test/home/user/important_file.txt などの絶対パスファイルの削除
  • ホームディレクトリ削除: ~/Documents/important.txt などの重要なファイルの削除
  • システムファイル削除: /etc/hosts/var/log/system.log などのシステムファイルの削除

実際の危険性

  • AIが意図しない解釈をしてファイルパスを間違える可能性
  • 複数のファイルを一度に削除する際の想定外の影響
  • プロジェクト外のファイルを削除してしまうリスク

他の制限方法の課題

Claude Code では settings.json の Deny 機能でコマンド制限も可能ですが、以下の制約があります:

  • 複数ファイル指定時の課題: rm file1.txt /tmp/test file2.txt のように安全なファイルと危険なファイルが混在する場合、制限が適用されない場合がある
  • オプション指定時の課題: -f-r などのオプションが指定された場合の制限適用
  • プロンプト表現による影響: AIへの指示の仕方によって制限動作が変わる可能性

PreToolUse hook による確実な制限

そこで本記事では、より確実な PreToolUse hook を使用したアプローチを採用しています。

この方法の特徴:

  1. 詳細なコマンド解析: コマンドライン全体を解析し、各引数を個別に検証
  2. 柔軟なカスタマイズ: プロジェクト固有の要件に応じた詳細なルール設定が可能
  3. 明確なフィードバック: 制限理由を具体的に表示し、JSON形式での結果出力
  4. 確実な動作: 複数ファイル指定やオプション指定でも安定した制限機能

設定手順

Step 1: ディレクトリ作成

まず、プロジェクトルートに ~/.claude/hooks/ ディレクトリを作成します:

mkdir -p ~/.claude/hooks

Step 2: 安全チェックスクリプトの作成

~/.claude/hooks/rm_safety_check.sh ファイルを作成します。

Step 3: 実行権限の付与

スクリプト作成後、実行権限を付与します:

chmod +x ~/.claude/hooks/rm_safety_check.sh

Step 4: 設定ファイルの場所

設定は ~/.claude/settings.json に記録されます:

{
  "PreToolUse": [
    {
      "matcher": "Bash",
      "hooks": [
        {
          "type": "command",
          "command": "~/.claude/hooks/rm_safety_check.sh $(jq -r .tool_input.command)"
        }
      ]
    }
  ]
}

スクリプト内容

~/.claude/hooks/rm_safety_check.sh として以下のスクリプトを作成:

#!/bin/bash

# rm コマンド安全性チェックスクリプト
# Claude Code の PreToolUse hook で使用
# JSON形式で結果を出力

# 引数をチェック
if [ $# -eq 0 ]; then
    echo '{"decision": "approve", "reason": "No command provided"}'
    exit 0
fi

# コマンドライン全体を取得
COMMAND_LINE="$*"

# rmコマンドかどうかをチェック
if [[ ! "$COMMAND_LINE" =~ ^rm[[:space:]] ]]; then
    # rmコマンドでない場合は許可
    echo '{"decision": "approve", "reason": "Not an rm command"}'
    exit 0
fi

# rmコマンドの引数を解析
# "rm" を除いた引数部分を取得
ARGS="${COMMAND_LINE#rm }"

# スペースで分割して各引数をチェック
IFS=' ' read -ra ARG_ARRAY <<< "$ARGS"

for arg in "${ARG_ARRAY[@]}"; do
    # オプション(-で始まる)はスキップ
    if [[ "$arg" =~ ^- ]]; then
        continue
    fi
    
    # 絶対パス(/で始まる)をチェック
    if [[ "$arg" =~ ^/ ]]; then
        echo "{\"decision\": \"block\", \"reason\": \"Absolute path deletion not allowed: $arg. Use relative paths within the project directory only.\"}"
        exit 2
    fi
    
    # ホームディレクトリパス(~で始まる)をチェック
    if [[ "$arg" =~ ^~ ]]; then
        echo "{\"decision\": \"block\", \"reason\": \"Home directory deletion not allowed: $arg. Use relative paths within the project directory only.\"}"
        exit 2
    fi
    
done

# すべてのチェックをパスした場合は許可
echo '{"decision": "approve", "reason": "rm command with safe relative paths"}'
exit 0

重要な機能

  • 複数ファイル対応: rm file1.txt file2.txt /tmp/test のように複数ファイルが指定された場合、各ファイルパスを個別にチェックし、1つでも絶対パスが含まれていれば全体をブロックします
  • オプション無視: -f-r などのオプションは安全性チェックの対象外とし、ファイルパスのみをチェックします

動作確認

1. テスト用ファイルの作成

まず、テスト用のファイルを作成します:

AI への依頼:

!touch /tmp/test を実行してください。

2. 危険なコマンドの実行テスト

以下のように AI に依頼してテストします:

依頼例(単一ファイル):

rm /tmp/test を実行してください。失敗することを望むのでエラー処理をしないでください。このコマンド以外を実行しないでください。

結果:

Bash operation blocked by hook:
- Absolute path deletion not allowed: /tmp/test. Use relative paths within the project directory only.

依頼例(複数ファイル):

rm temp1.txt /tmp/test temp2.txt を実行してください。失敗することを望むのでエラー処理をしないでください。このコマンド以外を実行しないでください。

結果:

Bash operation blocked by hook:
- Absolute path deletion not allowed: /tmp/test. Use relative paths within the project directory only.

説明: 複数ファイルが指定されても、1つでも絶対パスが含まれていれば全体がブロックされます。

3. 安全なコマンドの実行テスト

AI への依頼例:

!touch temp_file.txt を実行してください。

その後、rm temp_file.txt を実行してください。

結果: 正常に実行される(プロジェクト内の相対パス)

テストとカスタマイズ

スクリプトの直接テスト

スクリプトを直接実行してテスト:

bash ~/.claude/hooks/rm_safety_check.sh "rm /tmp/test"

出力例(ブロック時):

{"decision": "block", "reason": "Absolute path deletion not allowed: /tmp/test. Use relative paths within the project directory only."}

出力例(許可時):

bash ~/.claude/hooks/rm_safety_check.sh "rm temp_file.txt"
{"decision": "approve", "reason": "rm command with safe relative paths"}

出力例(rmコマンド以外):

bash ~/.claude/hooks/rm_safety_check.sh "ls -la"
{"decision": "approve", "reason": "Not an rm command"}

カスタマイズ例

特定のディレクトリのみ許可する場合:

# 特定のディレクトリのみ許可
if [[ "$arg" == "/tmp/"* ]]; then
    echo '{"decision": "approve", "reason": "tmp directory deletion allowed"}'
    exit 0
fi

デバッグモード

開発時はエラーログを確認:

# エラーの詳細出力
echo "{\"decision\": \"block\", \"reason\": \"Debug info: $COMMAND_LINE\"}" >&2

まとめ

PreToolUse hook を使用することで、Claude Code の強力な機能を保持しながら、危険な削除コマンドを事前に防ぐことができます。特に:

  1. 絶対パス削除の防止: システムファイルや重要なファイルの意図しない削除を防ぐ
  2. プロジェクト内の安全性: プロジェクトディレクトリ内での相対パスによる削除のみ許可
  3. カスタマイズ可能: プロジェクトの要件に応じてルールを調整可能

この仕組みにより、AI アシスタントとしての柔軟性を保ちながら、安全性を大幅に向上させることができます。

関連リンク

Discussion