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.
The SECRET entity type
Section titled “The SECRET entity type”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.
How secret detection works
Section titled “How secret detection works”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:
- A keyword pass selects the rules whose provider prefix or label appears in
the value, such as
ghp_orAKIA. - Each selected rule’s pattern runs over the value and extracts the credential from the match.
- Filters discard values that look like placeholders, such as
YOUR_API_KEYor a string of repeated characters, and values with too little entropy to be a real credential. - 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.
Where secret detection runs
Section titled “Where secret detection runs”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 aSECRET. For the policy model, see Policy contract. - Coding agent policies. The coding agent starter policies deny
SECRETin 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.
Secrets in stored values
Section titled “Secrets in stored values”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.
Secrets in coding agent sessions
Section titled “Secrets in coding agent sessions”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-inforefuses a developer prompt that pastes a credential. For more information, see Sensitive information in a developer’s prompt.coding-agent.session-analysisflags the session withcredential_accesswhen 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.
Taxonomy versions
Section titled “Taxonomy versions”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.
Example policy
Section titled “Example policy”The following policy screens a message that an agent writes before it posts the message to another system. It declares the following inputs:
| Input | Kind | Exposure |
|---|---|---|
message | String | SERVER |
external | Boolean | SERVER |
In the policy editor, add a sensitive information detector with the ID
secrets that reads message. In its deny list, select the following types:
SECRETCREDIT_CARD_NUMBEREMAILPHONE_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:
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.
Related
Section titled “Related”- Entity types – every sensitive information entity type and where Arcjet detects it
- Session analysis – flag a coding agent session after it reads a credential
- Sensitive information taxonomy versions – how a detector’s version works
- AI data loss prevention – keep sensitive data out of AI prompts