> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vikat.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Secrets Detection

> Catch leaked API keys, tokens and private keys in prompts and responses using regex guardrails.

<Warning>
  There is no Gitleaks-backed secrets provider. Earlier revisions of this page
  described one, with a curated rule pack and a `secrets_detection` provider type;
  it does not exist in the gateway. Secret detection is done with the `regex`
  provider type, which does work, and this page shows how.
</Warning>

## Why this matters in both directions

Credentials move through an LLM gateway two ways. A developer pastes a `.env`
file into a prompt asking why a service will not start, and the key is now in a
third-party provider's logs. Or a model, having been shown a credential earlier
in a conversation or in retrieved context, repeats it in an answer.

A `regex` guardrail with `apply_to: "both"` covers both directions with the same
rule.

## A working configuration

```json theme={null}
{
  "id": "secret-shapes",
  "name": "Credential shapes",
  "type": "regex",
  "enabled": true,
  "apply_to": "both",
  "message": "This request was blocked because it appears to contain a credential.",
  "patterns": [
    "AKIA[0-9A-Z]{16}",
    "ASIA[0-9A-Z]{16}",
    "sk-[A-Za-z0-9]{20,}",
    "sk-ant-[A-Za-z0-9\\-_]{20,}",
    "gh[pousr]_[A-Za-z0-9]{36}",
    "glpat-[A-Za-z0-9\\-_]{20}",
    "xox[baprs]-[A-Za-z0-9\\-]{10,}",
    "AIza[0-9A-Za-z\\-_]{35}",
    "-----BEGIN (?:RSA |EC |OPENSSH |PGP )?PRIVATE KEY-----",
    "eyJ[A-Za-z0-9_\\-]{10,}\\.[A-Za-z0-9_\\-]{10,}\\.[A-Za-z0-9_\\-]{10,}"
  ]
}
```

Paste it into the `providers` array of the guardrails plugin config, or build the
same thing on the **Guardrails → Providers** page in the console.

### What each pattern catches

| Pattern                         | Catches                                                  |
| ------------------------------- | -------------------------------------------------------- |
| `AKIA…` / `ASIA…`               | AWS access key IDs, long-lived and temporary.            |
| `sk-…`                          | OpenAI-style secret keys.                                |
| `sk-ant-…`                      | Anthropic API keys.                                      |
| `gh[pousr]_…`                   | GitHub personal, OAuth, user, server and refresh tokens. |
| `glpat-…`                       | GitLab personal access tokens.                           |
| `xox[baprs]-…`                  | Slack bot, app, user and refresh tokens.                 |
| `AIza…`                         | Google API keys.                                         |
| `-----BEGIN … PRIVATE KEY-----` | PEM private keys of any type.                            |
| `eyJ…`                          | JWTs, which frequently carry session identity.           |

## Things to know before turning this on

**Patterns are RE2.** No backtracking, no lookahead, no backreferences. That is
why a pattern cannot hang the gateway, and it is also why some expressions
written for PCRE will be rejected. A rejected pattern is refused at save time
with the reason and its position in the list.

**Blocking is the only outcome.** There is no redaction: a request containing a
key is refused, not stripped of it. There is also no log-only mode, so a new
pattern cannot be piloted without enforcing it — introduce patterns a few at a
time.

**False positives block real work.** `eyJ…` matches any base64 JSON object, not
only a JWT, and a long `sk-` prefixed identifier that is not a key will match
too. Start with the vendor-prefixed patterns, which are specific, and add the
generic ones once you have seen the traffic.

**Responses are scanned only if you ask.** `apply_to` defaults to `input`. The
configuration above sets `both` explicitly.

**Streaming is scanned as it arrives**, not only at the end, so the stream is cut
at the first chunk that completes a match. Chunks already sent cannot be
recalled — see the warning in [Guardrails](/enterprise/guardrails#responses-and-streaming).

## Coverage limits

The gaps that matter for credentials specifically:

* **File uploads and batch payloads are not scanned.** Uploading a file
  containing keys goes through unexamined, and that is the highest-volume way to
  move credentials through a gateway.
* **Non-JSON passthrough bodies are not scanned.**
* **MCP tool arguments and results are not scanned.**

The full list is in [Known gaps in coverage](/enterprise/guardrails#known-gaps-in-coverage).

## See also

* [Guardrails](/enterprise/guardrails) — the policy model, coverage, and what is
  not implemented.
* [Custom Regex](/enterprise/guardrails/custom-regex) — the same provider type
  applied to organisation-specific policy.
