Skip to main content

Prevent leaks with AI Hooks

AI Hooks make ggshield part of the AI coding tools your developers already use. When a prompt or a tool call contains a secret, ggshield blocks the action before it reaches the model and tells the developer or the agent what to remove. When a secret only appears in a tool's output, which a shell command or an MCP response can produce unpredictably, the action has already run. Some assistants let ggshield withhold that output so the model never sees it; on the rest, ggshield raises a desktop notification so the developer knows to rotate. See what each assistant supports.

Why AI Hooks matter on developer endpoints​

Endpoint scanning inventories the credentials already sitting on a machine. AI Hooks stop new ones from leaving it.

Developers using AI coding tools leak secrets at roughly twice the baseline rate. An agent asked to debug a failing deployment reads the .env file or ~/.aws/credentials and passes the contents to a model provider. There is no commit, no push, and no pull request, so none of the checkpoints that protect your repositories and CI ever fire.

Hooks act at the moment of the interaction, which gives you a few things:

  • Prevention rather than cleanup. A secret caught in a prompt or a tool call never reaches a third party, so there is no rotation to schedule and no model provider to ask about retention. The same holds for a tool's output on the assistants that let ggshield withhold it.
  • A fix the developer can act on. Every block names the detected secret and what to remove, so the developer or the agent can correct the content and retry immediately.
  • No extra agent to deploy. Hooks reuse the ggshield binary you already install for scanning. They run only when the AI tool calls them, so there is no resident process on the machine.

What hooks scan​

ggshield registers on three stages of an AI interaction:

  • Prompt submission: the prompt is scanned before it reaches the model, and blocked if it contains a secret.
  • Pre-tool use: file reads, shell commands, and MCP calls are scanned before the agent runs them, and blocked if they contain a secret.
  • Post-tool use: the tool has already run, so what ggshield can do depends on the assistant. Where the assistant allows it, the output is withheld and the model never sees the secret. Everywhere else the developer gets a desktop notification and the secret should be treated as exposed.

Detection uses the same engine as every other ggshield scan, covering 600+ types of secrets.

What each assistant supports​

The first two stages behave the same nearly everywhere: a secret in a prompt, in a command, or in a file about to be read is blocked before it reaches the model. The third stage is where assistants differ, because replacing a tool's output is something the assistant has to offer and most do not.

AssistantMinimum ggshieldSecret in a promptSecret in a command or file readSecret in a tool output
Claude Code1.49.0BlockedBlockedWithheld for shell commands and file reads, notification only for MCP and other tools
Cursor1.49.0, 1.55.0 on WindowsBlockedBlockedNotification only
VS Code1.51.0BlockedBlockedNotification only
Copilot CLI1.52.0BlockedBlockedNotification only
Codex1.53.0BlockedBlockedWithheld for every tool
Mistral Vibe1.54.0, with Vibe 2.21 or laterBlockedBlockedWithheld for every tool
Junie CLI1.55.0BlockedBlockedNot available: Junie runs no post-tool hook
Kiro CLI1.55.0BlockedBlockedNotification only
Kiro IDE1.55.0Detected, not blockedBlockedNotification only

Where the output is withheld, the assistant reads the ggshield message in place of the tool's output, so the secret never reaches the model provider and there is no need to rotate it. The message suggests how to keep the secret out of the next output instead, such as moving it to a secrets manager or not sharing the file with the agent. The command itself still ran, so any effect it had on your systems, such as an API call or an access log entry, still happened. Withholding requires ggshield 1.55.0 or later.

What stays on disk depends on the assistant. Claude Code writes the ggshield message to its session transcript in place of the output. Codex and Mistral Vibe still write the raw output to their own session files, the rollout files under ~/.codex/sessions/ and the Vibe session log, where no hook can reach it. That copy is local, so on its own it is no reason to rotate, but delete the session file if you don't want the secret kept there in plain text.

Where only a notification is possible, the assistant has already been given the output. Treat the secret as exposed and rotate it.

Three assistants need a note:

  • Junie is covered as the Junie CLI only. Junie inside a JetBrains IDE runs over ACP, which invokes no hooks, so nothing is scanned there.
  • Kiro CLI reads the hook configuration only in v3 mode. Start it with kiro-cli --v3; other sessions take their hooks from the agent configuration instead and the installed hook does not apply.
  • Kiro IDE cannot block a prompt. ggshield detects the secret, but the prompt still reaches the model. Treat the secret as exposed and rotate it.

For per-tool setup, what the blocking message looks like to a developer, and how to handle false positives, see Secret scanning for AI coding tools.

What a hook sends​

Detection happens on GitGuardian's side, so the content of the interaction is scanned by the API, the same way ggshield scans a commit or a push. Hooks also report each MCP tool call, with the tool and server name and the arguments the agent passed. That is what fills your MCP activity view and what carries the allow or deny decision back to the tool.

Machine scans work the other way around and keep detection on the endpoint. For the full breakdown of both, see Data handling & privacy.

Deploy AI Hooks across your fleet​

Hooks protect a machine only once they are configured on it, and asking each developer to opt in leaves gaps exactly where you need coverage. Push them through your MDM instead, alongside the rest of Endpoint Protection.

Scanning needs a token every time a hook fires, and because hooks run in the developer's own session rather than in your MDM job, that token has to be the developer's. Inject an admin service account token at runtime to install the hooks, then log the developer in so the hook scans under their membership: see Step 4 and Step 5.

To set up a single machine, run one command as the logged-in user:

ggshield machine setup

machine setup configures the hook for every AI coding assistant it detects, and skips the ones that are not installed. It also installs the git pre-commit and pre-push hooks and plants a honeytoken, so add --no-git-hooks or --no-honeytokens if you want AI Hooks alone. To pick or exclude specific assistants, use --agent or --exclude-agent with any of claude-code, codex, copilot, cursor, junie, kiro, vibe, and vscode.

machine setup requires ggshield 1.53.0 or later. The minimum version for each assistant's hook is listed in What each assistant supports. On earlier versions, install one assistant at a time with ggshield install -t <assistant> -m global, which still works but is deprecated.

Verify that hooks are active​

On a sample machine, as the logged-in user, run:

ggshield machine doctor

machine doctor is read-only and reports, for every assistant it finds on the machine, whether the hook is installed. It also checks that the token reaches GitGuardian and carries the scopes your protections need, and it exits non-zero if any check fails, so you can run it as an MDM audit script. Each failed check prints its own fix.

Both halves of that check matter. Because hooks fail open, a machine with hooks installed but no working credentials looks the same to a developer as a machine with nothing to block, apart from the warning that the content was not scanned.

To confirm end to end, paste a test credential into a prompt and check that the tool displays the ggshield blocking message.

Roll back​

Disabling the MDM setup job stops new machines from receiving hooks, but leaves the configurations already on disk in place. To remove them, delete the ggshield entries from the tool's hook configuration:

ToolHook configuration
Claude Code~/.claude/settings.json
Cursor~/.cursor/hooks.json
Codex~/.codex/hooks.json
Copilot CLI and VS Code~/.copilot/hooks/hooks.json
Mistral Vibe~/.vibe/hooks.toml
Kiro~/.kiro/hooks/ggshield.json
Junie~/.junie/config.json