Mode and debug flags use
CC_SAFETY_NET_* environment variables. Older SAFETY_NET_* names (without the CC_ prefix) are also accepted for strict, paranoid, paranoid-rm, paranoid-interpreters, and worktree toggles. See the environment variable reference for the full list, including CC_SAFETY_NET_DEBUG and CC_SAFETY_NET_HOME.Default Mode
No environment variables are required to get started. In default mode, CC Safety Net protects against all built-in destructive git and filesystem patterns. This is the recommended starting point for most users. Most malformed input is already handled safely regardless of mode:- Invalid hook input JSON is always blocked (fail-closed), in every mode.
- If the analyzer itself throws an unexpected error, the command is always blocked (fail-closed) with a “failed closed” reason, in every mode.
- If a command cannot be tokenized by the shell parser (for example, an unterminated quote), CC Safety Net runs a fallback text scan for known-dangerous patterns. If the scan matches, the command is blocked; if it does not match, the command is allowed through (fail-open). Strict mode changes only this last case.
Strict Mode (CC_SAFETY_NET_STRICT=1)
When strict mode is enabled, CC Safety Net switches to fail-closed behavior on commands that cannot be tokenized by the shell parser. Any command the parser cannot split into tokens is blocked rather than allowed, even if the fallback text scan finds no dangerous pattern.
Note that invalid hook input JSON and analyzer exceptions are already fail-closed in every mode — strict mode only tightens the unparseable-command case described above.
How to enable:
Paranoid Mode (CC_SAFETY_NET_PARANOID=1)
Paranoid mode enables additional safety checks that go beyond the defaults. These checks may be disruptive to some normal workflows, so they are opt-in. You can enable all paranoid checks at once, or activate individual checks selectively.
rm check (CC_SAFETY_NET_PARANOID_RM=1)
By default, rm -rf within the current working directory is allowed — the assumption is that deleting files inside your own project root is intentional. With the paranoid rm check enabled, all non-temp rm -rf commands are blocked, including those targeting paths inside the cwd.
Interpreter one-liners (CC_SAFETY_NET_PARANOID_INTERPRETERS=1)
Interpreter one-liners can hide destructive commands inside strings that are hard to inspect statically. With this check enabled, the following forms are blocked entirely:
python -c '...'node -e '...'ruby -e '...'perl -e '...'
CC_SAFETY_NET_PARANOID=1 is equivalent to enabling both CC_SAFETY_NET_PARANOID_RM=1 and CC_SAFETY_NET_PARANOID_INTERPRETERS=1 simultaneously.
Worktree Mode (CC_SAFETY_NET_WORKTREE=1)
Linked git worktrees are designed as disposable, isolated workspaces. Discarding changes inside one does not risk the main working tree, making the usual local-discard restrictions unnecessarily strict in that context. Worktree mode relaxes those rules — but only when CC Safety Net can positively confirm that the current working directory is inside a linked worktree.
How to enable:
What’s allowed inside a linked worktree
When worktree mode is active and the cwd is confirmed to be a linked worktree, the following commands are permitted:git restore <file>andgit restore --worktree <file>git checkout -- <file>,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
What remains blocked even in worktrees
These commands affect shared refs or other worktrees and are never relaxed, regardless of worktree mode:git push --force— affects the remotegit branch -D— force-deletes a branch that is shared across worktreesgit stash drop/git stash clear— the stash is shared across worktreesgit worktree remove --force— could delete another worktree
Detection and fail-closed behavior
Worktree detection is fail-closed: if CC Safety Net cannot positively identify the cwd as a linked worktree, the stricter default rules remain in effect. Specifically:- A linked worktree is identified by a
.gitfile (not a directory) whose resolved git directory contains acommondirfile. Main worktrees and submodules are not relaxed. - The cwd walk uses
realpathso symlinked paths resolve correctly. git -C <path>arguments are honored; unresolved targets keep the command blocked.- Relaxation is disabled if
--git-dir/--work-treeis passed, or ifGIT_DIR/GIT_WORK_TREE/GIT_COMMON_DIR/GIT_INDEX_FILEis set in the environment. - Certain local discards are never relaxed even inside a confirmed worktree: commands with dynamic arguments containing
$,*,?, or[; forced branch resets (git checkout -B/-Bforgit switch -C/-Cfwith-for--discard-changes);git cleanwith more than one-f; and any command using--recurse-submodules(or a recursive-submodule config).
Summary
| Variable | Effect |
|---|---|
CC_SAFETY_NET_STRICT=1 | Fail-closed on unparseable commands |
CC_SAFETY_NET_PARANOID=1 | All paranoid checks (rm + interpreters) |
CC_SAFETY_NET_PARANOID_RM=1 | Block rm -rf even within cwd |
CC_SAFETY_NET_PARANOID_INTERPRETERS=1 | Block interpreter one-liners |
CC_SAFETY_NET_WORKTREE=1 | Relax local-discard rules in linked worktrees |