Which safety level should I use?
Use the defaultstandard level for sessions you supervise. It is best-effort against adversarial or dynamic input. Use strict when commands may come from prompt injection or another untrusted context. Use paranoid to also block rm -rf inside the project and every python -c or node -e one-liner.
Each level is a preset of three capabilities:
Set the level with
safety.level in policy.json or the CC_SAFETY_NET_LEVEL environment variable. The higher of the two wins. The toggles on this page each turn on one capability on top of that level, and a combination that matches no preset reports as custom.
In linked Git worktrees, turn on worktree mode to allow local discards such as git reset --hard. For untrusted code or network control, add a sandbox.
See Environment for every variable and the precedence between policy and environment, and Policy for safety.overrides. What each safety level adds lists the affected commands.
Default mode
Default mode is thestandard safety level. It needs no environment variables and blocks the built-in destructive git and filesystem patterns and access to secret files.
Every level, standard included, blocks malformed hook input, an analyzer error, and a command too large or deeply nested to analyze. See Fail-closed enforcement.
Standard differs from strict on input it cannot parse or verify:
- A command that cannot be split into tokens, such as one with an unterminated quote, gets a scan for known dangerous patterns.
echo 'unterminatedruns, andgit reset --hard 'unterminatedblocks. See When standard cannot verify a command. - A recursive delete with a dynamic target, such as
rm -rf "$target", is allowed. Strict blocks it.
eval or source of one literal local generator such as eval "$(ssh-agent -s)".
Standard allows a check that a secret file exists without reading it, such as test -f .env or ls ~/.ssh. Strict and paranoid block these. What standard mode does not count as a read lists every such form. No level relaxes reading a secret file’s contents, a configured deny path, or a catastrophic rule.
When standard cannot verify a command
Two standard-level denials mean “could not verify” rather than “dangerous”:- Unparseable text that matched a destructive pattern.
- A shell command source CC Safety Net cannot resolve, such as
bash -c "$CMD".
Strict mode (CC_SAFETY_NET_STRICT=1)
Strict turns on the fail_closed capability. Expect occasional false positives on unusual syntax. It blocks:
- Unparseable commands, even when the text scan finds nothing dangerous. The reason is “Command could not be safely analyzed (strict mode)”.
echo 'unterminatedis allowed in standard and blocked here. - Heredocs outside a small supported set.
git commit -F - <<'EOF'and a plaincat <<'EOF'pass, but strict deniespython3 - <<'PY'. See Heredocs. - Unverifiable destructive targets, through the five rules below.
- Existence checks of secret files, such as
test -f ~/.ssh/id_rsaorfind ~/.ssh -type f. - Secret paths inside interpreter code that standard treats as data, such as
python -c "x = '.env'".
fail_closed is on:
Turn strict on with the level, or with the older toggle that sets the same capability:
You can turn off one of the five rules above with
destructive_command_protection.overrides in policy.json, or turn one on under standard with "on". Unparseable commands, unsupported heredocs, and secret-file checks have no rule you can turn off, so they stay blocked while strict is on.Paranoid mode (CC_SAFETY_NET_PARANOID=1)
The paranoid level is strict plus two capabilities, paranoid_rm and paranoid_interpreters. They can disrupt normal workflows, so they are opt-in. You can select the whole level or turn on each capability alone. CC Safety Net reports a level with only one of them as custom.
rm check (CC_SAFETY_NET_PARANOID_RM=1)
By default, CC Safety Net allows rm -rf and find -delete inside the current working directory. The paranoid rm check blocks non-temp recursive removal there too:
Temp targets and directories listed in
destructive_command_protection.allow_paths stay allowed.
Interpreter one-liners (CC_SAFETY_NET_PARANOID_INTERPRETERS=1)
Below paranoid, CC Safety Net blocks only a one-liner whose body contains a dangerous command, under rule interpreter.dangerous-command. With this check on, interpreter.one-liner-paranoid blocks every interpreter one-liner, whatever its content:
python -c '...'(alsopython3andpython2)node -e '...'ruby -e '...'perl -e '...'
python -c "print(1)" is allowed in standard and strict, and blocked here.
Enable paranoid checks
CC_SAFETY_NET_PARANOID=1 does not turn on fail_closed. Use CC_SAFETY_NET_LEVEL=paranoid or safety.level: "paranoid" for the full preset.
Worktree mode (CC_SAFETY_NET_WORKTREE=1)
A linked Git worktree is an isolated workspace, so worktree mode relaxes selected local-discard rules there. It applies only when CC Safety Net confirms that the current working directory is inside a linked worktree.
Enable worktree mode
workflow.worktree_mode: true in policy.json. Either setting turns worktree mode on.
Commands allowed in a linked worktree
In a confirmed linked worktree, worktree mode allows these commands:git restore <file>andgit restore --worktree <file>git checkout -- <file>,git checkout <path>,git checkout <ref> -- <file>,git checkout --force, and ambiguous multi-positional checkout formsgit reset --hardandgit reset --mergegit clean -f(and combined short flags like-fd)git switch --discard-changesandgit switch -f / --force
Commands blocked in linked worktrees
These commands affect shared refs or other worktrees, so worktree mode never relaxes them:git push --forceaffects the remotegit branch -Dforce-deletes a branch that is shared across worktreesgit stash drop/git stash clearchanges the stash shared across worktreesgit worktree remove --forcecould delete another worktree
git worktree remove --force can still pass when its target is a worktree directory under a temp directory such as /tmp. See Git commands in a temp repository.
When worktree mode does not apply
If CC Safety Net cannot confirm that the working directory is a linked worktree, the default rules stay in effect. Worktree mode never relaxes the main worktree or submodules.Other conditions that turn worktree mode off
Other conditions that turn worktree mode off
- The command passes
--git-diror--work-tree, or the environment setsGIT_DIR,GIT_WORK_TREE,GIT_COMMON_DIR, orGIT_INDEX_FILE. - The command sets
core.worktreethroughgit -corGIT_CONFIG_*, or the worktree’sconfig.worktreeor the shared repository config sets aworktreekey. - The worktree’s Git directory holds a symbolic link or a FIFO.
- CC Safety Net cannot resolve a
git -C <path>target. - An argument is dynamic, containing
$,*,?, or[. - The command uses
--recurse-submodulesor a recursive-submodule config. - The command force-resets a branch (
git checkout -Borgit switch -Cwith-for--discard-changes), or runsgit cleanwith more than one-f.