Skip to content

Detect secrets and API keys

A secret is a credential that grants access to a system: an API key, an access token, a private key, or a database connection string with a password in it. Anyone who holds the value can act as its owner until someone revokes it.

Secrets leak through text that moves between people, tools, and models. A developer pastes a .env file into a chat assistant to debug a configuration error. A coding agent runs cat .env or printenv and reads the output into its context. A support agent copies a customer’s webhook URL, signing secret included, into a ticket that an AI tool summarizes. Once the value is in a prompt, the model provider has a copy, and so does every log and tool that the prompt passes through.

Arcjet detects secrets in that text, so a policy can block the request or tool call before the credential leaves your control.

Arcjet reports every credential that it finds as one entity type, SECRET. Version 3 of the sensitive information taxonomy adds it. For every entity type and the version that added it, see Entity types.

There’s one type rather than one type per provider, because a policy decides whether a credential is present, not which provider issued it. The provider rules change as providers introduce and retire token formats, and a policy that named one of those rules would break when the rule changed. To tell you which credential Arcjet found, each finding carries the ID of the rule that matched it, such as github-pat, aws-access-token, or stripe-access-token. The rule appears with the finding in Activity in the Arcjet Console and in the detected_entities field of the Arcjet API.

A policy’s Rego sees only the type. input.signals.sensitive_info lists SECRET and never the rule, the same as for every other entity type.

Arcjet matches credentials against a set of rules, each of which describes one credential format, such as a GitHub personal access token or a PEM private key. Together, the rules cover hundreds of formats across cloud providers, payment processors, source control hosts, messaging platforms, and AI model providers.

Arcjet checks each value in the following stages:

  1. A keyword pass selects the rules whose provider prefix or label appears in the value, such as ghp_ or AKIA.
  2. Each selected rule’s pattern runs over the value and extracts the credential from the match.
  3. Filters discard values that look like placeholders, such as YOUR_API_KEY or a string of repeated characters, and values with too little entropy to be a real credential.
  4. When two rules match overlapping text, Arcjet keeps the finding from the more specific rule.

The rules describe formats that providers issue, so they’re precise. They don’t flag a value only because it’s long or random, and they don’t detect a password that a person chose. To detect a credential format that’s specific to your organization, use custom entity detection.

Arcjet never sends a credential to its provider to check whether it’s live, and it ignores the inline allow comments that some secret scanners honor. A comment like that would let whoever wrote the text exempt their own credential from detection.

Secret detection runs in the server-side sensitive information detector of an agent guard policy. Arcjet reads the value on its own servers, so the detector reads a SERVER policy input. You can use it in the following places:

  • Agent guard policies. A guard() call in your application passes the text as a server input, and the policy denies the call when the detector finds a SECRET. For the policy model, see Policy contract.
  • Coding agent policies. The coding agent starter policies deny SECRET in developer prompts and flag the session when a tool result shows one. For more information, see Secrets in coding agent sessions.

The SDK-local options don’t detect SECRET. The sensitiveInfo HTTP rule and the SDK-local detector in a policy run in your process with Rampart and detect the version 1 types.

Arcjet runs the secret rules itself, with no call to a model. A detector whose deny list names only SECRET adds no model latency to a guard call. Arcjet scans the whole value rather than a prefix. If the scan can’t finish, the detector returns no verdict, and a live rule that reads it fails closed.

A server input sends its raw value to Arcjet. For what Arcjet receives and how long it keeps it, see Privacy.

Arcjet masks every credential that it finds in the values that it stores, such as request details, policy input evidence, and coding agent captures. It does this whether or not a policy screens for SECRET, and after policies evaluate, so a policy always reads the unmasked value.

A masked credential keeps its first four characters, but never more than a quarter of its length, so the provider prefix stays readable. Every other character becomes *. For example, ghp_ followed by 36 characters is stored as ghp_ followed by 36 asterisks. The text keeps its length, so the offsets of other findings still point at the right characters. If Arcjet can’t finish scanning a value, it masks the whole value rather than store it unscanned.

Coding agents read credentials as part of ordinary work. An agent that’s debugging a deployment reads .env files, prints environment variables, and opens configuration files, and everything that it reads goes into the model’s context.

The coding agent starter policies deny SECRET in the following ways:

  • coding-agent.sensitive-info refuses a developer prompt that pastes a credential. For more information, see Sensitive information in a developer’s prompt.
  • coding-agent.session-analysis flags the session with credential_access when a tool result shows a credential, then refuses web and MCP calls for the rest of the session. The hook that reports a tool result runs after the tool has run, so the agent has already read the credential. The flag limits what the agent can do with it. Shell and file tools keep working, so local work continues. For more information, see Session analysis.

Arcjet screens shell output for SECRET alone. Shell output is where an agent most often reads a credential, and the other entity types match too much unrelated text in build logs and command output. If shell output is too long to scan whole, Arcjet scans its beginning and doesn’t flag the session with incomplete_screen.

A server-side detector stays on the taxonomy version that it was written against, so a policy that you published before version 3 doesn’t start reporting SECRET. A detector below version 3 also never runs the secret rules. A detector that you add uses the current version and covers SECRET. To add SECRET to an existing detector, move the detector to version 3, then add SECRET to its deny list. For more information, see Sensitive information taxonomy versions.

The following policy screens a message that an agent writes before it posts the message to another system. It declares the following inputs:

InputKindExposure
messageStringSERVER
externalBooleanSERVER

In the policy editor, add a sensitive information detector with the ID secrets that reads message. In its deny list, select the following types:

  • SECRET
  • CREDIT_CARD_NUMBER
  • EMAIL
  • PHONE_NUMBER

The policy’s Rego denies a message that carries a credential anywhere, and a message that carries any listed type when it leaves your organization:

Policy
package arcjet.guard
import rego.v1
# Deny a message that carries a credential, wherever it goes.
deny contains "secret-in-message" if {
"SECRET" in input.signals.sensitive_info.secrets.entities
}
# Deny a message that carries any listed type when it leaves your
# organization.
deny contains "sensitive-info-to-external" if {
input.signals.sensitive_info.secrets.detected
input.values.external
}

The detector’s result is under input.signals.sensitive_info.secrets. detected is true when the detector finds a listed type, and entities lists the types that it found. To deny on every listed type with no Rego, declare a DETECTOR rule over the detector instead. For more examples, see Policy examples.

Put new rules in dry run first, as described in Author and publish policies, and review what the detector finds in your own traffic before you block on it.

Secret scanning for AI applications and agents

Section titled “Secret scanning for AI applications and agents”

Secret scanning has mostly meant scanning source code. Repository scanners such as Gitleaks and GitHub secret scanning look for API keys and tokens that a developer committed, in a pre-commit hook, a CI job, or a push. That catches a credential in a repository, but not one that a person pastes into an AI chat, or one that an agent reads from a file and sends to a model provider. Those leaks never touch a commit.

Arcjet applies secret detection at runtime, to the text that flows through an AI application or an AI agent. In your own application, an agent guard policy detects leaked API keys in LLM prompts, access tokens in tool call arguments, and private keys in tool output, and blocks the text before your code forwards it to a model, a log, or a third-party service. This is data loss prevention (DLP) for AI: the same credential leak prevention that a repository scanner gives your source code, applied to prompts, tool calls, and agent output.

For coding agents such as Claude Code, Cursor, GitHub Copilot, and OpenAI Codex, Arcjet screens the developer’s prompts and the agent’s tool results from the hooks that the agent already runs. A prompt hook runs before the model sees the prompt, so Arcjet can refuse a prompt that pastes a credential. A tool result hook runs after the tool has run, so Arcjet can’t withhold the result from the agent. Instead, when an agent reads a secret from a .env file or prints an environment variable, Arcjet records the finding, flags the session, and refuses the web and MCP calls that could exfiltrate the credential. This helps protect against both accidental leaks and prompt injection attacks that try to steal credentials.

For your own applications, an agent guard policy screens any text that you pass to guard(): a user’s chat message, a document that a retrieval-augmented generation (RAG) pipeline loads, or the output of a tool before your agent forwards it. One detector covers API key detection, token detection, and private key detection across cloud, payment, source control, and AI provider formats, with the matching rule recorded for each finding.