Skip to content
Agentic Control Plane

API key prefixes: which service issued this key?

David Crowe David Crowe · · Updated · 13 min read
secrets env api-keys reference
Share X HN LinkedIn

An API key’s first few characters usually name the service that issued it. pplx- is Perplexity, tvly- is Tavily, xai- is xAI, fw_ is Fireworks AI, sk-ant- is Anthropic, ghp_ is GitHub. If you found one in a .env, a log, a commit or an agent transcript, the table below tells you whose dashboard to open, and the sections after it cover rotation and keeping coding agents out of .env.

The prefix table

Each row is checked against the vendor’s own docs. Where we could not confirm a prefix on a vendor page, the row says so instead of guessing.

Prefix Issuer What it is Source
pplx- Perplexity API key Perplexity API key management
tvly- Tavily API key Tavily headers and authentication
xai- xAI API key xAI accounts and authorization
fw_ Fireworks AI API key Fireworks docs
fpk_ Fireworks AI Fire Pass key Fireworks Fire Pass
sk-ant-api Anthropic Claude API key (sk-ant-api03-... in examples) Claude API authentication
sk-ant-admin Anthropic Admin API key Claude Admin API
sk-, sk-proj- OpenAI, widely reported API key, project key Unverified: no OpenAI page we could load states the prefix
AIza Google Google Cloud API key Google Cloud API keys
ghp_ GitHub Personal access token (classic) GitHub token expiration and revocation
github_pat_ GitHub Fine-grained personal access token same
gho_ / ghu_ / ghs_ / ghr_ GitHub OAuth app / user-to-server / server-to-server / refresh token GitHub’s token formats post
sk_live_ / sk_test_ Stripe Secret key, live / sandbox Stripe API keys
rk_live_ / rk_test_ Stripe Restricted key same
pk_live_ / pk_test_ Stripe Publishable key (safe in client code) same
hf_ Hugging Face User access token Hugging Face user access tokens
r8_ Replicate API token Replicate API tokens
ntn_ Notion Integration token (since September 25, 2024) Notion changelog
secret_ Notion (older tokens), also generic Integration token created before the switch to ntn_ same
up_ Unverified No vendor source found —
sn4_ Unverified No vendor source found —

Notes on the rows:

  • sk- versus sk_. Anthropic and the OpenAI-style keys use a hyphen. Stripe uses an underscore. A sk_live_ key is Stripe and it is live money.
  • secret_ alone tells you little. Notion used it until September 2024, and older Notion tokens still work. Other tools use it too. Check the variable name next to it in the file.
  • Notion advises against validating its tokens with a regex, because the format can change. A prefix helps you triage a finding. It is not a contract.
  • up_ and sn4_. We found no vendor page that claims either one. Don’t trust a blog that names an issuer without a link to the vendor. Look at the variable name and the code that reads it.

People usually land here for one of three reasons:

  • A scanner flagged it. GitHub secret scanning, a pre-commit hook or a CI job reports a match and shows only the first few characters.
  • It showed up in an agent transcript. A coding agent opened .env to debug something and quoted a value back.
  • It is in a file nobody remembers creating. An old .env in a repo you just inherited.

The next step is the same each time: find the issuer, rotate the key, then close the leak. A key in a transcript or a public commit counts as leaked even if nobody has used it yet. Our piece on how agents leak .env secrets covers the usual paths.

How to rotate each one

Rotate means: create a new key, deploy it wherever the old one was read, then disable or delete the old one.

Issuer Where Notes from the vendor docs
Perplexity API portal, or the /generate_auth_token and /revoke_auth_token endpoints A revoked key cannot be recovered
Tavily Your Tavily dashboard Replace TAVILY_API_KEY
xAI xAI Console, API Keys page Keys are bound to a team; the full key is shown once
Fireworks AI Fireworks account settings Replace FIREWORKS_API_KEY
Anthropic Claude Console, API keys page Disable is reversible, Delete is permanent; set an expiration on the new key
OpenAI OpenAI platform API keys page Replace OPENAI_API_KEY
Google Google Cloud console, API keys Add API and application restrictions to the new key
GitHub Your GitHub token settings POST /credentials/revoke takes a ghp_ or github_pat_ token and needs no authentication
Stripe Dashboard, API keys Stripe says to rotate a leaked key immediately; prefer a restricted rk_ key for the replacement
Hugging Face Settings → Access Tokens POST https://huggingface.co/api/credentials/revoke revokes leaked tokens in bulk
Replicate replicate.com/account/api-tokens Disable the token, create a new one
Notion Your integration’s settings New tokens come out as ntn_

Two vendor tips. Stripe’s key best practices suggest searching your code, config and CI for sk_live_ and rk_live_. Anthropic’s docs suggest an expiration on every key, so a leaked one stops working on its own.

Keep coding agents out of .env

Rotation fixes the last leak. These settings make the next one less likely. Each tool’s controls are different, and each has a gap.

Claude Code

Add Read deny rules in .claude/settings.json (Claude Code permissions):

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)"
    ]
  }
}

Bare filenames follow gitignore rules, so Read(.env) matches any .env at or under the current directory. Use // for an absolute path and ~/ for your home directory.

Per the docs, Read deny rules cover the built-in file tools, Bash file commands Claude Code recognizes (cat, head, tail, sed, tee) and redirect targets. They do not cover grep -r pattern . run from the directory that holds the file, or a Python or Node script that opens the file itself. For that, the docs point to the sandbox. A .claudeignore file has no effect. Our deny rules not working post lists the reported bypasses.

Codex

Codex blocks paths through a permission profile in ~/.codex/config.toml (Codex permissions):

default_permissions = "project-edit"

[permissions.project-edit]
extends = ":workspace"

[permissions.project-edit.filesystem]
glob_scan_max_depth = 3

[permissions.project-edit.filesystem.":workspace_roots"]
"." = "write"
"**/*.env" = "deny"

deny blocks both reads and writes from sandboxed commands, and deny wins over write and read on the same path. Two limits from the docs: on Linux, WSL and native Windows, deny globs are expanded when each sandboxed process starts, so a .env created later stays readable to that process; and an unbounded ** pattern needs glob_scan_max_depth. An admin can enforce reads denied for every user with deny_read under [permissions.filesystem] in requirements.toml.

Check it on your version. openai/codex#22179 reported deny globs not blocking reads in 0.130.0 under the older syntax. For a hook that blocks edits to .env, see Codex hooks examples.

Cursor

Cursor ignores .env* by default, along with everything in .gitignore (Cursor ignore files). Ignored files are blocked from Agent, Tab and @ mentions. Add more in .cursorignore:

**/.env
**/.env.*
**/*.pem

The gap, in Cursor’s words: “The terminal and MCP server tools used by Agent cannot block access to code governed by .cursorignore.” An agent that runs cat .env in the terminal still reads it. Cursor also notes that complete protection isn’t guaranteed.

OpenCode

OpenCode 2’s default policy asks before reading *.env and *.env.*, and allows *.env.example (OpenCode permissions). To deny instead of ask, add rules to opencode.jsonc. The last matching rule wins, so the exception goes last:

{
  "$schema": "https://opencode.ai/config.json",
  "permissions": [
    { "action": "read", "resource": "*.env", "effect": "deny" },
    { "action": "read", "resource": "*.env.*", "effect": "deny" },
    { "action": "read", "resource": "*.env.example", "effect": "allow" }
  ]
}

This is the V2 format: permissions, shell and subagent replace V1’s permission, bash and task. The read rule covers the read tool. A shell command that prints the file is a separate shell action, so review your shell rules too.

What this does not cover

A prefix names the issuer. It does not prove the key is live, and it does not tell you who used it. Only the vendor’s usage logs answer that.

Every agent control above lives inside one tool. Each has a documented way around it, usually the shell, and none of them carries over to the next tool. The strongest fix is to keep real secrets out of files an agent can open. Load them from a secrets manager at run time and keep only .env.example in the repo.

ACP can add a record. It checks each tool call from the harness hooks and logs it, so you can see which commands touched which files, and it redacts secrets in the stored previews. Be clear about the limit: ACP’s read-and-send detector (a sensitive file like .env named in the same command as curl, wget, scp or nc) ships off unless a preset turns it on. Don’t count on ACP to stop a .env read. The install box below sets up the logging in one line.

Frequently asked questions

pplx- leak .env: whose key is it?

A key starting with pplx- is a Perplexity API key. Perplexity’s API key management docs show generated tokens in that form. If one leaked, revoke it (the docs list a revoke_auth_token endpoint, and keys can be managed in the API portal) and generate a new one.

tvly- and xai- keys: which services?

tvly- is Tavily, the search API; its docs show Authorization: Bearer tvly-YOUR_API_KEY. xai- is xAI, the Grok API; its key management reference shows keys returned in the form xai-… Rotate both in the vendor console.

What are fw_, secret_, up_ and sn4_ keys?

fw_ is Fireworks AI; its docs refer to a standard Fireworks key as fw_…. secret_ is the older Notion integration token prefix (new Notion tokens start with ntn_), though other tools also use secret_. We could not verify an issuer for up_ or sn4_ from a vendor source, so we do not name one.

How do I prevent Codex from reading .env?

Use a permission profile in ~/.codex/config.toml whose filesystem block marks “*/.env” = “deny” under :workspace_roots, set glob_scan_max_depth, and make it the default_permissions. Deny blocks both reads and writes from sandboxed commands. Files created after a process starts are not added to its deny list.

ai coding tools env file exposure: which tools read .env by default?

Claude Code reads files in the working directory without asking unless you add a Read deny rule. Cursor ignores .env* by default for Agent and Tab, but not for terminal or MCP tools. OpenCode’s default policy asks before reading *.env. Codex blocks it only when a permission profile denies it.

Where to read more

Running coding agents? ACP records each tool call its hook sees and makes the dangerous shell commands (a force-push, destructive SQL, curl | sh) wait for you. One command, free up to 5 agents:

macOS · Linux · WSL
curl -fsSL https://agenticcontrolplane.com/install.sh | bash
Windows · PowerShell
irm https://agenticcontrolplane.com/install.ps1 | iex

What the installer writes  ·  Getting started

Share X HN LinkedIn
Get the next data drop
What agents actually cost, new tool-surface captures, and the occasional incident post-mortem — sent when we publish something worth your inbox, not on a schedule. Unsubscribe anytime.
Share: Twitter LinkedIn
Related posts

← back to blog