standard、strict、paranoid という 3 つの安全レベルがあります。各レベルは、同じ 3 つの機能に展開される preset です。独立した処理経路ではなく、機能の組み合わせに付けた名前です。
レベルは、
policy.json の safety.level または環境変数 CC_SAFETY_NET_LEVEL で設定します。実際に適用される基本レベルは、この 2 つのうち高い方です。このページで説明する個別のトグルは、その基本レベルの上に機能を 1 つだけ追加します。3 つの preset のいずれとも完全には一致しない組み合わせは、有効なレベルが custom として報告されます。
既定モード
既定モードはstandard 安全レベルです。環境変数を設定しなくても、組み込みの破壊的な Git 操作とファイルシステム操作をブロックします。まずはこのレベルを使ってください。
次の失敗は、どのレベルでも同じように扱います。
- hook の入力 JSON が不正な場合は、どのモードでも常にブロックします(fail closed)。
- アナライザー自体が予期しないエラーを投げた場合は、どのモードでも「failed closed」という理由を付けてコマンドを常にブロックします(fail closed)。
- パーサーの再帰上限または構造検証の上限を超えるコマンドは、どのモードでも常にブロックします。このリソース枯渇を防ぐための上限は、standard レベルでも緩和されません。
- シェルのパーサーがコマンドをトークンに分割できない場合(引用符が閉じていない場合など)、CC Safety Net は既知の危険なパターンをフォールバックのテキストスキャンで探します。一致すればブロックし、一致しなければそのコマンドを通します。そのため
echo 'unterminatedは許可されますが、git reset --hard 'unterminatedはヒューリスティックなスキャンによって引き続きブロックされます。 - standard では、動的な再帰削除の対象を一律にはブロックしません。
rm -rf "$target"はここでは許可され、fail closed 機能を有効にして初めてブロックされます。
eval "$(ssh-agent -s)" のように完全にリテラルなローカルの生成コマンド 1 つに対する eval/source です。これらは意図的なトレードオフです。standard は、敵対的な入力や動的な入力に対してはベストエフォートという位置づけです。コマンドがプロンプトインジェクションなど敵対的な文脈から渡される可能性がある場合は、strict または paranoid を使ってください。
一方で standard でも、緩和されないものがあります。機密情報の内容へのアクセス、ユーザーが設定した deny path とその配下、そして致命的な操作に対する保護(root とホームディレクトリの再帰削除、Git メタデータ、正規の policy.json)です。
Strict モード(CC_SAFETY_NET_STRICT=1)
strict モードは fail_closed 機能を有効にします。厳しくなるのは解析できないコマンドだけではありません。次の 5 点が変わります。
- 解析できないコマンドをブロックします。 フォールバックのテキストスキャンで危険なパターンが見つからなかった場合でも、パーサーがトークンに分割できないコマンドは「Command could not be safely analyzed (strict mode)」として拒否します。
echo 'unterminatedは standard では許可されますが、ここではブロックされます。 - heredoc を fail closed で扱います。 次の条件をすべて満たす場合を除き、heredoc を含むコマンドを拒否します。標準入力を対象とする展開されない heredoc が 1 つだけで、他に入力リダイレクトがなく、読み取り側が
cat、tee、git apply、git commit、gh pr create、gh issue createのいずれかとしてリテラルに書かれていることが必要です。展開されない heredoc とは、デリミタが引用符で囲まれているもの(<<'EOF')か、引用符がなくても本文に$、バッククォート、バックスラッシュが含まれないものを指します。そのためpython3 - <<'PY'や、本文に$HOMEを含むcat <<EOFは拒否され、git commit -F - <<'EOF'と、本文がプレーンテキストだけのcat <<EOFは許可されます。正確な条件は heredoc の解析を参照してください。 - 下に挙げる 5 つのルールによって、検証できない破壊的対象をブロックします。
- メタデータのみで機密パスを探る操作をブロックします。
test -f ~/.ssh/id_rsaとfind ~/.ssh -type fは standard では許可され、strict では拒否されます。 - standard 限定のインラインデータ緩和が無効になります。 standard では、Node や Bun のインライン評価に機密パスのリテラルが含まれていても、上限付きの字句スキャンでファイルシステム操作やコマンド実行の痕跡が見つからなければ、実害のない診断用データとして扱います。strict ではこの緩和がなくなります。
fail_closed が有効なときにだけ動作します。
hook の入力 JSON が不正な場合、アナライザーの例外、パーサーのリソース上限による失敗は、どのモードでもすでに fail closed です。strict が新たに追加する動作ではありません。
strict 安全レベルを有効にする
CC_SAFETY_NET_STRICT=1 も同じ機能を有効にするもので、引き続き使用できます。
strict 安全レベルを使用する場合
コマンドが敵対的な文脈や信頼できない経路から渡される可能性がある場合は、strict モードを有効にしてください。保護を最大限に高めたい場合や、珍しいコマンド構文でときどき誤検知が出ても許容できる場合にも適しています。policy.json の
destructive_command_protection.overrides を使うと、strict 相当のルールを個別に無効にできます。逆に "on" の override を指定すれば、standard でも任意の strict 相当ルールを強制的に有効にできます。ただし、パーサーの fail closed や機密パスに関する判定など、破壊的コマンドのルール ID を持たない fail closed の結果については、strict は引き続き strict のまま動作します。Paranoid モード(CC_SAFETY_NET_PARANOID=1)
paranoid レベルは、strict に paranoid_rm と paranoid_interpreters の 2 つの機能を加えたものです。これらのチェックは通常のワークフローを妨げることがあるため、明示的に有効にしたときだけ動作します。レベル全体を選ぶことも、個別の機能だけを有効にすることもできます。片方しか有効になっていない場合、有効なレベルは custom として報告されます。
rm チェック(CC_SAFETY_NET_PARANOID_RM=1)
既定では、カレントディレクトリ配下の rm -rf は許可されます。自分のプロジェクトルート内のファイルを削除するのは意図的な操作だ、という前提に立っているためです。paranoid の rm チェックを有効にすると、カレントディレクトリ配下であっても、一時パス以外への再帰的な強制削除をブロックします。rm -rf ./cache は rm.recursive-force-paranoid に一致し、PowerShell の同等コマンドである Remove-Item ./cache -Recurse -Force は powershell.remove-item-recursive-force-paranoid に一致します。
このチェックを有効にしても、一時パスと destructive_command_protection.allow_paths に指定したディレクトリは許可されたままです。
インタープリターの 1 行コード(CC_SAFETY_NET_PARANOID_INTERPRETERS=1)
インタープリターの 1 行コードは、静的には検査しにくい文字列の中に破壊的なコマンドを隠せてしまいます。paranoid 未満のレベルでは、本体に危険なコマンドを含む 1 行コードだけをブロックします(ルール interpreter.dangerous-command)。このチェックを有効にすると、内容にかかわらずすべての 1 行コードを interpreter.one-liner-paranoid でブロックします。
python -c '...'(python3とpython2も含む)node -e '...'ruby -e '...'perl -e '...'
python -c "print(1)" は standard と strict で許可され、ここではブロックされます。
paranoid 安全レベルを有効にする
fail closed 動作なしで両方の paranoid チェックを有効にする
個別の paranoid チェックを有効にする
CC_SAFETY_NET_PARANOID=1 を設定することは、CC_SAFETY_NET_PARANOID_RM=1 と CC_SAFETY_NET_PARANOID_INTERPRETERS=1 の両方を有効にするのと同じです。ただし fail_closed は有効になりません。そのため、既定の standard レベルに重ねた場合、有効なレベルは paranoid ではなく custom になります。preset 全体を適用したい場合は、CC_SAFETY_NET_LEVEL=paranoid(または safety.level: "paranoid")を使ってください。
Worktree モード(CC_SAFETY_NET_WORKTREE=1)
Git の linked worktree は、独立した作業環境として使えます。worktree モードは、カレントディレクトリが linked worktree の中にあると CC Safety Net が確認できた場合にかぎり、一部のローカル破棄ルールを緩和します。
worktree モードを有効にする
workflow.worktree_mode: true を設定することもできます。この 2 つは論理 OR として扱われ、どちらか一方でも設定されていれば worktree モードが有効になります。
linked worktree 内で許可するコマンド
worktree モードが有効で、カレントディレクトリが linked worktree だと確認できた場合、次のコマンドを許可します。git restore <file>とgit restore --worktree <file>git checkout -- <file>、git checkout <ref> -- <file>、git checkout --force、および位置引数が複数あって判別しにくい checkout の形式git reset --hardとgit reset --mergegit clean -f(-fdなど、組み合わせた short flag を含む)git switch --discard-changesとgit switch -f / --force
linked worktree 内でもブロックするコマンド
次のコマンドは共有された ref や他の worktree に影響するため、worktree モードの有無にかかわらず緩和されることはありません。git push --force:リモートに影響するgit branch -D:worktree 間で共有されるブランチを強制削除するgit stash drop/git stash clear:stash は worktree 間で共有されるgit worktree remove --force:別の worktree を削除しかねない
linked worktree の検出
worktree の検出は fail closed です。カレントディレクトリを linked worktree と確実に特定できない場合は、より厳しい既定のルールを適用します。条件は次のとおりです。- linked worktree は、解決後の Git ディレクトリに
commondirファイルを持つ.gitファイル(ディレクトリではない)によって識別します。メインの worktree と submodule は緩和の対象外です。 - カレントディレクトリからの探索には
realpathを使うため、シンボリックリンクを含むパスも正しく解決されます。 git -C <path>の指定は考慮します。対象を解決できない場合、そのコマンドはブロックされたままです。--git-dir/--work-treeを渡した場合や、環境変数にGIT_DIR/GIT_WORK_TREE/GIT_COMMON_DIR/GIT_INDEX_FILEが設定されている場合は、緩和を無効にします。- 確認済みの worktree 内でも、次のローカル破棄は緩和されません。
$、*、?、[を含む動的な引数を持つコマンド、ブランチの強制リセット(git checkout -B/-Bf、または-fや--discard-changesを伴うgit switch -C/-Cf)、-fを複数指定したgit clean、--recurse-submodules(または submodule を再帰的に扱う設定)を使うコマンドです。
安全レベルのまとめ
worktree モードはレベルとは独立しており、確認済みの linked worktree 内でローカル破棄ルールを緩和します。
レベルを選択する変数や機能を強制する変数の一覧、以前の
SAFETY_NET_* エイリアス、policy.json と環境変数の詳しい優先順位については、環境変数を参照してください。