> ## Documentation Index
> Fetch the complete documentation index at: https://ccsafetynet.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# How CC Safety Net Intercepts and Blocks Bash Commands

> How CC Safety Net intercepts Bash commands, runs semantic analysis, detects shell wrappers, and returns block decisions before execution.

CC Safety Net hooks into your AI agent's tool execution pipeline so it runs *before* any shell command executes. For most agents this is a PreToolUse hook; the exact mechanism varies by agent (Claude Code and Kimi Code use a `PreToolUse` hook on the `Bash` tool, Gemini CLI uses a `BeforeTool` hook on `run_shell_command`, Copilot CLI uses a preToolUse hook, and Pi loads CC Safety Net as an in-process extension). See [Integration Architecture](/docs/guides/integration-architecture) for the per-agent details. Rather than maintaining a list of forbidden strings, CC Safety Net parses each command into its components and reasons about intent. This page walks through exactly what happens between the moment your agent builds a command and when (or whether) that command runs.

## The Hook Pipeline

<Steps>
  <Step title="Agent prepares a Bash command">
    Your AI agent constructs a shell command to execute — for example, `git reset --hard` — and passes it to the Bash tool.
  </Step>

  <Step title="PreToolUse hook fires">
    Before the Bash tool executes anything, CC Safety Net intercepts the call. This happens at the hook layer, which runs *before* the permission system and before the OS ever sees the command.
  </Step>

  <Step title="Semantic analysis">
    CC Safety Net parses the command into its components — executable, subcommand, flags, and arguments — and analyzes the intent of the operation. See [Semantic Analysis](#semantic-analysis) below for details.
  </Step>

  <Step title="Decision returned">
    If the command is determined to be destructive, the agent receives a `BLOCKED` response with a human-readable reason explaining what the command does and what to do instead. If the command is safe, it is allowed through and executes normally.
  </Step>
</Steps>

## Semantic Analysis

CC Safety Net uses semantic analysis rather than simple string matching. This distinction matters in practice.

When a command arrives, it is parsed into its structural components:

* **Executable** — the base program (`git`, `rm`, `find`, etc.)
* **Subcommand** — the operation being requested (`checkout`, `reset`, `push`, etc.)
* **Flags** — options that modify behavior (`--hard`, `-f`, `-r`, etc.)
* **Arguments** — the targets the command acts on (file paths, branch names, refs, etc.)

With this parsed representation, CC Safety Net reasons about *what the command will do*, not just *what it looks like*. Consider two commands that share the same base:

| Command                   | Intent                                 | Outcome     |
| ------------------------- | -------------------------------------- | ----------- |
| `git checkout -b feature` | Creates a new branch                   | **Allowed** |
| `git checkout -- file`    | Discards uncommitted changes in a file | **Blocked** |

Both start with `git checkout`. A pattern-matching approach either blocks both or neither. Semantic analysis distinguishes them and makes the right call in each case — protecting you from accidental data loss without blocking everyday workflows.

## Shell Wrapper Detection

Wrapping a destructive command in a shell invocation doesn't hide it from CC Safety Net. Shell wrappers like `bash -c '...'` are recursively unwrapped and the inner command is subjected to the same semantic analysis. This unwrapping goes up to **10 levels deep**.

```bash theme={"dark"}
bash -c 'git reset --hard'    # → analyzed → BLOCKED
sh -lc 'rm -rf /'             # → analyzed → BLOCKED
```

This means an agent cannot bypass protection simply by embedding a blocked command inside a shell invocation.

## Interpreter One-Liner Detection

Destructive commands can also be hidden inside interpreter one-liners. By default, CC Safety Net extracts the code passed to an interpreter's `-c` or `-e` flag — for `python`, `python2`, `python3`, `node`, `ruby`, and `perl` — and scans it for embedded destructive operations:

```bash theme={"dark"}
python -c 'import os; os.system("rm -rf /")'  # BLOCKED
```

If you want stricter behavior, set `CC_SAFETY_NET_PARANOID_INTERPRETERS=1` to block *all* interpreter one-liners outright — regardless of their content.

## Block Output Format

When CC Safety Net blocks a command, the agent receives a structured response as the tool result. A typical block message looks like this:

```text theme={"dark"}
BLOCKED by CC Safety Net

Reason: git checkout -- discards uncommitted changes permanently. Use 'git stash' first.

Command: git checkout -- src/main.py

If this operation is truly needed, ask the user for explicit permission and have them run the command manually.
```

The agent reads this as the tool response and typically surfaces the explanation to you. The message tells the agent what went wrong, why it's dangerous, and how to proceed safely — either by using a safer alternative or by asking you to run the command manually with explicit intent.

## Audit Logging

Blocked commands are written to a structured log file for later review:

```text theme={"dark"}
~/.cc-safety-net/logs/<session_id>.jsonl
```

Each entry in the log is a JSON object on its own line:

```json theme={"dark"}
{"ts": "2025-01-15T10:30:00Z", "decision": "deny", "command": "git reset --hard", "segment": "git reset --hard", "reason": "...", "cwd": "/path/to/project"}
```

| Field      | Description                                                                                                  |
| ---------- | ------------------------------------------------------------------------------------------------------------ |
| `ts`       | ISO 8601 timestamp of when the command was handled                                                           |
| `decision` | The decision CC Safety Net made: `deny` (blocked) or `allow` (permitted)                                     |
| `command`  | The full command string as received, truncated to 300 characters                                             |
| `segment`  | The specific segment that triggered the block, truncated to 300 characters (may differ for wrapped commands) |
| `reason`   | The human-readable reason for blocking                                                                       |
| `cwd`      | The working directory at the time of the call                                                                |

A few details worth knowing:

* **Denied commands are always logged** when a session id is available; **allowed commands are logged only when `CC_SAFETY_NET_DEBUG=1`** is set, to keep the log focused on interventions.
* Commands blocked because the analyzer itself failed (the fail-closed safety net) are **not** written to the log.
* Nothing is written when there is no session id available.
* The `doctor` command summarizes this log as its **Recent Activity** check (blocked commands from the last 7 days).

Sensitive data (tokens, passwords, API keys) in log entries is automatically redacted before they are written to disk. See the [audit log reference](/docs/reference/audit-log) for the full redaction scope.

## Secret Redaction

Block messages and log entries both go through automatic secret redaction before being surfaced to the agent or written to disk. This ensures that if a destructive command happens to include a token, credential, or API key in its arguments, that sensitive data is never exposed in agent responses or audit logs.

## Known Limitations

CC Safety Net analyzes the command string your agent attempts to run, so it cannot catch everything — for example behavior hidden inside arbitrary binaries, transparent command proxies, reads and network activity, and a few parser edge cases. See [Known Limitations](/docs/guides/known-limitations) for the full list and the recommended mitigations.

If you believe a destructive command slipped through, run `npx cc-safety-net explain "<command>"` to see the analysis, and report genuine bypasses as described in the [security policy](/docs/security).

<Note>
  For the system component view and data-flow diagrams, see [Architecture](/docs/guides/architecture). For a deep dive on each analyzer and the `rm -rf` classification hierarchy, see [Analysis Engine](/docs/guides/analysis-engine). For the design rationale behind this approach, see [Design Principles](/docs/guides/design-principles).
</Note>
