Skip to main content

Which safety level should I use?

Use the default standard 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 the standard 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 'unterminated runs, and git reset --hard 'unterminated blocks. See When standard cannot verify a command.
  • A recursive delete with a dynamic target, such as rm -rf "$target", is allowed. Strict blocks it.
Standard also allows dynamic executables, commands assembled through substitution, and 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".
On Claude Code, in most permission modes, these two ask you to approve the command instead of blocking it. Other hosts, and strict and paranoid, keep the deny. See When Claude Code asks you instead of blocking.

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 'unterminated is allowed in standard and blocked here.
  • Heredocs outside a small supported set. git commit -F - <<'EOF' and a plain cat <<'EOF' pass, but strict denies python3 - <<'PY'. See Heredocs.
  • Unverifiable destructive targets, through the five rules below.
  • Existence checks of secret files, such as test -f ~/.ssh/id_rsa or find ~/.ssh -type f.
  • Secret paths inside interpreter code that standard treats as data, such as python -c "x = '.env'".
These five rules activate only when 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 '...' (also python3 and python2)
  • node -e '...'
  • ruby -e '...'
  • perl -e '...'
So 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

You can also set 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> and git restore --worktree <file>
  • git checkout -- <file>, git checkout <path>, git checkout <ref> -- <file>, git checkout --force, and ambiguous multi-positional checkout forms
  • git reset --hard and git reset --merge
  • git clean -f (and combined short flags like -fd)
  • git switch --discard-changes and git switch -f / --force

Commands blocked in linked worktrees

These commands affect shared refs or other worktrees, so worktree mode never relaxes them:
  • git push --force affects the remote
  • git branch -D force-deletes a branch that is shared across worktrees
  • git stash drop / git stash clear changes the stash shared across worktrees
  • git worktree remove --force could delete another worktree
Without worktree mode, 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.
  • The command passes --git-dir or --work-tree, or the environment sets GIT_DIR, GIT_WORK_TREE, GIT_COMMON_DIR, or GIT_INDEX_FILE.
  • The command sets core.worktree through git -c or GIT_CONFIG_*, or the worktree’s config.worktree or the shared repository config sets a worktree key.
  • 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-submodules or a recursive-submodule config.
  • The command force-resets a branch (git checkout -B or git switch -C with -f or --discard-changes), or runs git clean with more than one -f.
Check the level in effect with npx cc-safety-net status, or with the status line in Claude Code.
Last modified on October 27, 2026