DLP coverage and locales
Control Zero scans the outbound traffic your agent generates — tool-call arguments and the prompts sent to a model — for sensitive data, across PII, financial, healthcare, and secrets categories. The gateway can also scan the model's replies on the way back, which is off by default and covered under Response-Side DLP. You can also add custom regex rules for organization-specific data.
In the SDK and the coding-agent hooks, all 65 built-in patterns are active immediately, with no configuration. US SSNs, Korean RRNs, AWS keys and the rest all match out of the box.
The gateway groups its patterns into 12 locale and category sets and activates default (28 patterns) unless you ask for more, because a Korean RRN pattern running against US-only traffic is mostly false positives. CZ_GATEWAY_DLP_LOCALES selects the sets; see Pattern sets and how to enable them.
Which surfaces scan, and in which direction, is set out exactly in Where DLP runs.
What's covered out of the box
Personal identifiers (PII)
Identifiers that vary by region. The detector recognizes:
| Region | Patterns |
|---|---|
| United States | SSN, phone numbers (with area code variants) |
| Korea | Resident Registration Number (RRN) with Mod-11 check digit, mobile, business registration (BRN), driver license, passport, bank account |
| Japan | My Number (individual), My Number (corporate), mobile phone |
| Europe | UK National Insurance Number, German Steuer-ID, French NIR (social security) |
| India | Aadhaar, PAN |
| Brazil | CPF |
| Canada | SIN |
| Australia | TFN |
| Singapore | NRIC / FIN |
| Hong Kong | HKID |
| Universal | Email addresses |
Financial
| Pattern | Notes |
|---|---|
| Credit card | Luhn checksum validated (Visa, Mastercard, Amex, Discover, JCB) |
| IBAN | International bank account, country prefix validated |
| SWIFT / BIC | Bank identifier codes |
| US routing number | ABA routing |
| Bitcoin address | Legacy P2PKH and P2SH |
| Ethereum address | EOA and contract addresses |
Healthcare
| Pattern | Notes |
|---|---|
| US NPI | National Provider Identifier (10 digits) |
| US DEA Number | Drug Enforcement Administration registration |
Secrets and credentials
The detector catches accidental key leaks for cloud providers, AI services, version control, payments, observability, and infrastructure:
- Cloud: AWS Access Key, AWS Secret Key, GCP API Key, GCP Service Account Key, Azure Client Secret, Azure SAS Token
- AI providers: OpenAI, Anthropic, HuggingFace, Cohere
- Version control: GitHub PAT, GitLab PAT
- Payments: Stripe Publishable Key, Stripe Secret Key
- Communications: Slack Bot Token, Slack Webhook URL, SendGrid API Key
- Package registries: npm Token, PyPI Token
- Infrastructure: SSH Private Key, PEM Certificate, Vault Token, JWT Token, Bearer Token (Authorization header)
- Connection strings: PostgreSQL, MySQL, MongoDB, Redis, AMQP / RabbitMQ
- Observability: Datadog, Sentry DSN, New Relic, Linear
- Control Zero: Control Zero API keys (so you don't accidentally paste your own key into a chat)
Pattern sets and how to enable them
Locale sets apply to the gateway. The SDK and the coding-agent hooks run the full built-in catalog already, so nothing here needs enabling for them.
On the gateway, patterns are grouped into 12 sets and only default is active out of the box; add the others by name.
| Set | Patterns | Covers |
|---|---|---|
default | 28 | US and universal identifiers, cards, core secrets |
ko | 10 | Korea: RRN, BRN, mobile, licence, passport, bank |
ja | 7 | Japan: My Number (individual and corporate), mobile |
eu | 6 | UK NINO, German Steuer-ID, French NIR |
financial | 5 | Extended banking and crypto identifiers |
secrets | 5 | Extended credential and token shapes |
medical | 3 | US NPI, DEA registration |
hk | 1 | Hong Kong HKID |
id | 1 | Indonesia NIK |
my | 1 | Malaysia NRIC |
sg | 1 | Singapore NRIC / FIN |
tw | 1 | Taiwan national ID |
Sets overlap slightly, so the 12 sets together resolve to 64 unique patterns. default plus eu, ja, ko, medical and secrets resolves to 59.
On the gateway, set the list with CZ_GATEWAY_DLP_LOCALES (comma-separated, no spaces):
CZ_GATEWAY_DLP_LOCALES=default,ko,ja,secrets
Action per finding
Each pattern runs with one of three actions:
| Action | What happens to the call | Use when |
|---|---|---|
detect | Call proceeds. Finding is recorded in the audit log. | You want visibility without disrupting users |
mask | Replaces the match in-place and lets the call proceed on Claude Code and Gemini CLI through the Python SDK; denies everywhere else | You use supported Python hook masking |
block | Call is denied. Agent receives a policy-denied error. | High-risk data: credentials, customer PII in code |
You can mix actions per pattern. Mask credit cards only for Claude Code or Gemini CLI through the Python SDK; use block elsewhere.
Adding custom regex rules
Real organizations have data shapes the built-in patterns won't cover: internal project codes, customer account IDs, proprietary identifiers. Add them via the DLP Rules Editor in the dashboard, or directly in your policy file:
dlp_rules:
- id: internal-project-code
pattern: 'PROJ-[A-Z]{3}-\d{6}'
category: custom
action: block
reason: 'Internal project codes must not leave the agent'
- id: customer-account-id
pattern: 'CUST_[0-9]{10}'
category: pii
action: mask
reason: 'Redact on supported Python hooks; deny elsewhere'
- id: jira-ticket
pattern: '\bACME-\d{4,6}\b'
category: custom
action: detect
reason: 'Track which agents reference internal tickets'
Patterns use Python re syntax (a PCRE-compatible subset). Test patterns from the dashboard editor before publishing -- it runs them against sample text live so you can confirm matches and check for false positives.
The mask rule above replaces the sensitive value in-place and lets the call
proceed on Claude Code and Gemini CLI through the Python SDK. It denies the call
everywhere else.
Where DLP runs
Each surface covers a different direction, and two of them need a switch thrown first. This table is the authority:
| Surface | Direction | Where the scan happens | Active by default |
|---|---|---|---|
| SDK | Tool call args | Before guard() returns | Yes |
| Coding hooks | Tool call arguments before the AI assistant executes them | In the hook check | Yes |
| Gateway — request | The prompt sent to the LLM | In the proxy, before forwarding | Yes |
| Gateway — response | The model's reply | In the proxy, before the reply is returned | No — set CZ_GATEWAY_RESPONSE_DLP_ENABLED=true |
| Browser extension | Text typed or pasted into chat UIs | In the browser before the request leaves | Once a DLP profile is configured — see below |
| MCP server | The tool arguments a client submits for a check | Locally, in the MCP server process | Only when the client calls the guard tool |
Two limits worth stating plainly:
- The browser extension ships no patterns of its own; it is served them. It fetches its rule set from your organization, and the server merges your enabled built-in detectors in with your custom
browser_extrules -- so SSNs, AWS keys and card numbers are caught in the browser without writing a custom rule for each. Two conditions and one exclusion are worth knowing. The merge requires DLP to be switched on for your org and a project or organization DLP profile to be configured; with no profile, the extension receives your custombrowser_extrules only. And detectors that need surrounding context to hit their intended precision are deliberately not sent to the browser, so a small number of built-ins are enforced by the SDK and gateway but not in the extension. If the server cannot resolve your profile it returns an error rather than quietly serving a reduced rule set -- but be clear what that means at the browser: with no rules loaded the extension does not scan and does not block. It records that non-enforcing state in the audit trail with a distinct reason and warns you once per session, so the gap is visible rather than silent; it is still a gap, not a block. See the browser extension guide. - The MCP guard is cooperative, not enforcing. It scans the
tool_args_texta client chooses to submit and returns a decision the client may ignore, and it does not scan tool outputs. Put the SDK or the gateway in the path when a deny has to stop execution. See MCP Cooperative Guard.
What you see in the audit log
Every finding -- whether it triggered a block, mask, or just a detect -- is recorded with the rule id, the category, the action taken, and a count of matches. The original matched text is not logged unless you explicitly opt in to that. Audit answers "this happened" without itself becoming a sensitive data store.
Availability
Built-in DLP patterns are available on Free, Solo, and Teams tiers. Custom DLP rules and the dashboard rules editor are available on Solo and Teams. Approval workflows and DLP rule version history are available on Teams.
Next steps
- DLP Rules Editor -- add custom rules from the dashboard
- Gateway proxy -- enable DLP on existing agents with no code changes
- Coding assistant hooks -- DLP in Claude Code, Cursor, Gemini CLI, Codex CLI