Kno2gether kno2gether.com ↗ Try Knotie free
Field Guide

Your Claude Code security hook may have been guarding nothing

Before v2.1.176, hook if conditions on Read/Edit/Write tool paths silently didn't match — so the guard you wrote for .env, src/ globs, or ~/.ssh never fired. Here's the copy-paste hook and the 30-second test that proves yours actually blocks.

See how Knotie white-labels for you
01

The silent gap (and why it mattered)

If you write Claude Code hooks, you've probably added an if condition to guard a sensitive path — block a Read of your .env, an Edit anywhere in src/**, a Read of ~/.ssh/**. The catch: before version 2.1.176, those documented path patterns silently failed to match. The hook never fired. No block, no error — just a guard quietly doing nothing. The Claude Code v2.1.176 changelog states it directly: 'Fixed hook if conditions for Read/Edit/Write tool paths: documented patterns like Edit(src/**), Read(~/.ssh/**), and Read(.env) now match correctly.'
Important and honest: the changelog confirms the patterns weren't matching. It does NOT mean anyone read your secrets — it means the guard you THOUGHT was active wasn't. Treat it as a false sense of security to close, not a confirmed breach.
02

Step 1 — Upgrade to 2.1.176 or later

The fix ships IN 2.1.176, so 2.1.176 itself already has it. Update Claude Code, then confirm the version before you trust any path-based hook again.
  1. Update: claude update (or reinstall via your package manager / npm, however you installed it).
  2. Confirm: claude --version and check it reads 2.1.176 or higher.
  3. Only after you're on >= 2.1.176 is it worth wiring up (or trusting) a path-scoped guard hook.
If you're on a version below 2.1.176, assume every path-pattern hook condition you wrote was inactive.
03

Step 2 — The copy-paste protective hook

This is a PreToolUse hook that blocks the model from reading or editing your most sensitive paths. Put it in your project's .claude/settings.json (or your user-level settings) and tighten the paths to your repo:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Read",
        "if": "Read(.env) || Read(.env.*) || Read(~/.ssh/**) || Read(**/secrets/**)",
        "command": "echo 'BLOCKED: sensitive read' >&2; exit 2"
      },
      {
        "matcher": "Edit|Write",
        "if": "Edit(.env) || Write(.env) || Edit(~/.ssh/**) || Edit(**/*.pem)",
        "command": "echo 'BLOCKED: sensitive write' >&2; exit 2"
      }
    ]
  }
}
  • exit 2 is the signal a PreToolUse hook uses to BLOCK the tool call (a non-zero deny). A zero exit would allow it.
  • Match Read separately from Edit/Write — they're different tool names, and you usually want different paths blocked for each.
  • Tighten the globs to YOUR layout: add **/config/credentials*, **/*.key, your terraform state, etc.
Pattern shown for illustration — the exact if-condition syntax and settings fields are version-sensitive, so verify against the Claude Code hooks documentation for your version before you rely on it. And after editing settings.json, restart Claude Code (or start a new session) so the hook is loaded — hooks are read at startup, not hot-reloaded.
04

Step 3 — The 30-second test that proves it fires

Never trust a security hook you haven't watched block something. This is the whole point: a hook you never tested isn't protection — it's a guess. Run this once and watch the deny happen in real time.
  1. In a session on >= 2.1.176, ask Claude plainly: 'Read the contents of .env' (a path your hook guards).
  2. Watch for the block: the tool call should be DENIED and your hook's message ('BLOCKED: sensitive read') should surface — the file contents must NOT come back.
  3. Repeat for an Edit/Write on a guarded path (e.g. 'edit ~/.ssh/config') and confirm that's denied too.
  4. If it does NOT block: re-check your version (>= 2.1.176), confirm the hook is in the settings file Claude actually loaded, and that the glob matches the real path you triggered.
Green test = the guard is live. No block = you're still exposed; fix the version or the pattern and re-test before you rely on it.
05

Bonus 30-second check — Remote Control silent model switch

The same v2.1.176 release fixed a second silent issue worth a quick look: 'Fixed Remote Control connecting from web/mobile silently switching the session's model.' If you connect to a running session from the web or mobile app, your session's model could change without telling you — which may have quietly put you on a different model than you intended.
  • If you use Remote Control (web/mobile) to attach to sessions, upgrade to >= 2.1.176 so the connect no longer silently swaps your model.
  • After connecting from web/mobile, glance at the active model indicator and confirm it's the one you meant to run.
  • This is a 'while you're in there' check — not the headline, but a free win once you've already upgraded.
Both fixes are 'silent failure' bugs: the dangerous kind, because nothing warned you. Upgrading closes both.
06

Make it a habit — the principle

Path-pattern matching is fixed now, but the lesson outlives this one release: a guard is only real once you've seen it deny. Bake a verify step into how you ship hooks.
  • Every time you add or change a security hook, run the 30-second deny test before you trust it.
  • Keep the test trivially cheap (one prompt per guarded path) so you'll actually do it.
  • Treat 'it didn't error' as NOT the same as 'it blocked' — silent success is the trap this whole episode is about.

Get the next drop

New AI build guides + the occasional bonus template. No spam, unsubscribe anytime.

By submitting you agree to our Privacy Policy & Terms. Unsubscribe anytime.

Frequently asked questions

Does this mean my secrets were leaked?
No. The changelog only confirms the path patterns weren't matching, so the guard you wrote wasn't active. It's a false sense of security to close, not a confirmed breach. Rotate anything you're genuinely unsure about, but don't panic.
Which version has the fix?
Version 2.1.176. The fix ships in that release, so 2.1.176 or any later version is fine — 'upgrade to 2.1.176 or later.'
How does a PreToolUse hook block a call?
It exits with a non-zero status (e.g. exit 2) to deny the tool call before it runs. A zero exit allows it. That's why the 30-second test matters — you want to SEE the deny.
Do I need to restart Claude Code after editing settings.json?
Yes — start a new session (or restart). Hooks and skills are read at startup, so an edit to settings.json won't take effect mid-session.

You just hardened your own Claude Code. Want to sell that kind of safe, configured AI to clients under your brand?

Knotie is a white-label AI platform: you resell voice agents, chat agents, and automations under your own brand and domain, with credit billing and your margin built in. The hard part of an AI service business isn't the tech — it's shipping something clients trust. Knotie gives you the platform; you bring the relationship.

See how Knotie white-labels for you