Security2026-10-147 min read

Claude Code Hooks Can Now Fail Closed. Turn It On for Every Hook You Call a Control

Claude Code 2.1.296, released on 9 October 2026, adds onFailure: "block" for command and HTTP hooks, so a hook that cannot start, times out or exits with an unexpected code stops the action instead of waving it through. It is a one line setting, and it is the difference between a guardrail and a suggestion.

On 9 October 2026 Anthropic shipped Claude Code 2.1.296 with a small entry in the changelog that matters more than its length suggests. Command hooks and HTTP hooks now accept onFailure: "block". With it set, a hook that cannot start, times out, or exits with an unexpected code blocks the action it was guarding instead of letting it through. Hooks are the main way teams bolt their own checks onto Claude Code: a script that refuses writes outside the repository, an HTTP call to a policy service before a shell command runs, a secrets scanner before a commit. Until now, if that check itself broke, the agent carried on. This release gives you a way to make a broken check stop the work.

Last week we wrote about Copilot Studio hooks, where a failed hook lets the agent continue, and argued that a guardrail which steps aside when it breaks is not yet a control. The same logic applies here, and the Claude Code change is the fix we said to look for. A check that only runs when everything is healthy protects you on good days. The days you actually need it are the bad ones: the policy service is down, the scanner binary was removed in an image rebuild, the script hits a timeout on a huge diff, or someone renamed a path in the settings file. In all of those cases the old behaviour quietly turned your control off, and nothing in the session told you it had happened.

Be precise about what the setting covers. It applies to command and HTTP hooks, and it triggers on three failure modes: the hook could not start, it timed out, or it exited with a code the runtime did not expect. It does not change what happens when your hook runs correctly and decides to allow something, and it does not make a weak rule strong. A hook that checks the wrong thing will still pass the wrong thing. What it removes is the silent gap between we have a control and the control actually ran. That gap is exactly what an auditor probes when they ask how you know a preventive control operated for the whole period, not just when you tested it.

Here is how to roll it out without breaking your developers. First, list every hook in your user, project and managed settings, and sort them into two groups: hooks that enforce something you would describe as a control, and hooks that are convenience, such as formatting, notifications or logging. Set onFailure: "block" on the first group only. A notification hook that fails should not stop a refactor; a hook that stops writes to production credentials should. Second, test the failure path on purpose. Point the HTTP hook at an unreachable host, rename the script, or force a timeout, and confirm the action is refused. Third, make the refusal message say which hook failed and who owns it, because a blocked developer with no explanation will find a way around the block.

Then push the control hooks through managed settings rather than project files. A project settings file lives in the repository, and anything in the repository can be edited by the agent or by a pull request. Managed settings are set by the organisation and sit above user and project settings. The same release family is moving in this direction elsewhere: version 2.1.283 changed managed sandbox settings so that one invalid nested value fails closed for that value while the rest of the block still applies, rather than the whole sandbox block being ignored. Taken together, the direction is clear. Configuration errors and runtime errors in security settings should lead to less access, not more.

There is a mod angle too. Earlier this month we covered Claude Code mods, which run unsandboxed TypeScript and can respond to permission prompts. If your organisation allows mods, assume one can interfere with the behaviour of other checks, and keep your enforcement hooks in managed settings where a mod or a project file cannot quietly remove them. Review the list of approved mods the same way you review a browser extension list. The point of fail closed is lost if the hook can simply be deleted, so pair this setting with a check that the hook is still present, for example a scheduled job that reads the effective settings on a sample of developer machines and alerts when a control hook is missing.

For compliance teams, this is a clean piece of evidence to collect. Under ISO 27001 it supports secure development and the configuration management controls: you can show the setting, the test of the failure path, and the change record for the day it went live. Under ISO 42001 it belongs in the operational controls for an AI system, specifically the human and technical oversight measures around an agent that can write code and run commands. Under SOC 2 it is a preventive control in change management, and the failure path test is your test of operating effectiveness. If you run Vanta or Drata, attach the managed settings file, a screenshot or log of the blocked test, and the hook owner to the control, and set a review date so the test is repeated after major Claude Code upgrades.

If you also use Cursor, Devin, GitHub Copilot or Copilot Studio, ask the same question of each one: when a hook, rule or policy check errors, does the agent stop or continue? Write the answer in your AI tool register with the version you checked and the date. Vendors change this behaviour quietly in point releases, in both directions, and the only way to know is to test it. Our guide to AI coding agents covers what each tool can do; this is the line in the register that tells you whether the controls you configured actually hold when something goes wrong.

A short plan for this week. Upgrade Claude Code to 2.1.296 or later across the team. Inventory every hook and mark which ones are controls. Add onFailure: "block" to those, deliver them through managed settings, and break each one on purpose to prove the block works. Record the change, the test and the owner against your ISO 27001, ISO 42001 or SOC 2 control. Then repeat the failure test whenever Claude Code updates. It is perhaps an hour of work, and it turns a guardrail that only works on good days into one you can defend in an audit.

Claude Codehooksfail closedAI coding agentsguardrailsmanaged settingsCopilot StudioCursorDevinISO 27001ISO 42001SOC 2VantaDrata

Editorial note: AES Tech reviews are independent. Some outbound links are affiliate links and are marked sponsored; they never change our rankings. See our disclosure.

// Signal, not noise

Get the next post by email

One short email when something worth knowing ships. No spam, unsubscribe anytime.

Loading comments...

Add a comment

Corrections and first-hand experience are the most useful things you can leave. Comments are screened automatically and reviewed by a human; see the moderation policy.

0/4000 · plain text · links are held for review

More from the blog