Coco

Can the agent get past it

What was tested, what happened, and what is still true afterwards.

Can the agent get past it

The first question every engineer asks, and it deserves a measurement rather than an argument.

Reproduce all of it with tests/enforcement_probe.sh, which takes about a minute.

What was tested

A throwaway PreToolUse hook in a throwaway directory. It logs what it saw, then returns a decision for Bash. Claude Code is asked to run echo <marker>, and the transcript is checked for the marker to see whether the command actually ran.

Environment. Claude Code 2.1.228, August 2026.

What happened

Permission modeHook decisionHook firedCommand ran
defaultdeny, exit 2yesno
bypassPermissions (--dangerously-skip-permissions)deny, exit 2yesno
defaultaskyesno
bypassPermissionsaskyesno

The hook also reported the mode it was running under.

hook fired  tool=Bash  permission_mode=bypassPermissions

What that means

A permission mode does not turn the gate off. --dangerously-skip-permissions skips Claude Code's own permission prompts. A PreToolUse hook runs before that prompt, so skipping the prompt does not skip the hook.

The documentation says the same thing in two places. Hooks run before the permission prompt, for every tool, and a hook that exits 2 stops the tool call before permission rules are evaluated.

This is worth stating plainly because the opposite is widely repeated, including by people who ship hooks of their own. On the version tested here, the flag does not bypass the hook. The evidence is version-specific by nature, which is why the probe ships in the repository. Run it on the version you actually deploy, and run it again as part of every runtime upgrade, because a measurement from last quarter is not a control.

An escalation that cannot reach anyone does not become a pass. In a non-interactive session there is nobody to answer a prompt, and the call stopped rather than proceeding. Coco does not rely on that. In a mode that cannot ask, the gate converts ESCALATE to BLOCK itself, so the receipt says what actually happened rather than recording an escalation nobody could have answered.

What still gets past it

Said before a customer finds them.

Editing the settings file. The hook is registered in a settings file, and anyone who can write that file can remove the gate. On a managed fleet the answer is managed settings, which a user cannot override, together with allowManagedHooksOnly, which blocks user and project hooks so only the organisation's hooks load. disableBypassPermissionsMode and disableAutoMode close the modes as well, though on this evidence they are not the hole.

A different client. The gate governs sessions on a machine where it is installed. An agent run somewhere else is not governed by it, which is an argument for deploying it as policy rather than as a developer's choice.

Everything that is not a tool call. The gate sees the actions an agent takes. It does not read what the model says, and it does not contain what a permitted action does once it is running. A contract that permits a database write cannot then supervise the write.

A wrong contract. The gate enforces what is written. A rule that is too loose passes things it should not, and no amount of enforcement fixes a rule nobody checked. This is why observe mode exists and why the catch report is the artefact that decides whether to enforce.

Next

On this page