Claude API Environment Variable Security Guide
Why Environment Variables Are the Default, and Why That's Not Enough
If you're asking how to secure a Claude API environment variable, the short answer is: never hardcode the key, load it from a .env file locally that is excluded from version control, inject it as a platform secret in production, scope it as narrowly as possible, and rotate it on a schedule plus immediately after any suspected leak. Environment variables are the right storage mechanism for API keys — they keep secrets out of your source code and let the same codebase run against different credentials in dev, staging, and production.
But "use an env var" is the easy 80%. The remaining 20% — how the variable gets into the environment, who can read it, how it's logged, and what happens when it leaks — is where most real incidents happen. This guide covers the practical controls that actually prevent a Claude API key (or a SubToAPI key, which follows the same patterns) from ending up in a GitHub repo, a log aggregator, or a client-side bundle.
The Core Mistakes That Leak Keys
Almost every leaked API key traces back to one of these:
- Committing
.envfiles. A developer addsANTHROPIC_API_KEY=sk-ant-...to.env, forgets to add.envto.gitignore, and pushes it. GitHub's secret scanning catches some of this, but private repos and forks are often missed. - Printing env vars in logs.
console.log(process.env)during debugging, or a crash handler that dumps the full environment, ships straight into a log aggregator that dozens of people can search. - Shipping keys to the browser. Any variable prefixed for client bundling (
NEXT_PUBLIC_,VITE_,REACT_APP_) gets compiled into JavaScript that anyone can view in DevTools. API keys should never carry one of these prefixes. - Sharing one key across environments. Using the same key for local dev, staging, and production means a compromised laptop compromises production too, and you can't tell which environment caused unusual usage.
- Long-lived keys with no rotation plan. A key issued two years ago, never rotated, with no record of who has access to it, is a liability even if it hasn't leaked yet.
Setting Up Environment Variables Correctly
Local development
Keep secrets in a .env file that is git-ignored from day one:
# .gitignore
.env
.env.*
!.env.example
Commit a .env.example with placeholder values so teammates know what's required without ever seeing a real key:
# .env.example
ANTHROPIC_API_KEY=sk-ant-your-key-here
SUBTOAPI_KEY=sub_live_your-key-here
Load it with a library like dotenv rather than exporting variables manually in your shell history, which itself can leak through ~/.bash_history or ~/.zsh_history.
CI/CD pipelines
Store secrets in your CI provider's encrypted secret store (GitHub Actions secrets, GitLab CI variables, CircleCI contexts), not in the pipeline YAML. Mask them in logs — most providers do this automatically for variables registered as secrets, but verify it; a misconfigured echo $SUBTOAPI_KEY in a debug step defeats masking entirely.
Production
Use your host's secret manager rather than a flat .env file on disk:
- Vercel/Netlify: environment variables per deployment target (production/preview/development)
- AWS: Secrets Manager or Parameter Store, injected at runtime
- Docker/Kubernetes: secrets mounted as files or injected via a secrets operator, not baked into the image
Never bake an API key into a Docker image layer — anyone with pull access to the image can extract it from the layer history even if it's removed in a later layer.
Scoping, Rotation, and Monitoring
Environment variable hygiene is only half the problem. The other half is what the key can actually do if it does leak.
- Use separate keys per environment and per service. If your Claude integration has multiple consumers (a web app, a background worker, an internal tool), issue separate keys for each. A compromised worker key shouldn't let an attacker call the API as your web app.
- Rotate on a schedule. Treat key rotation like certificate renewal — pick an interval (quarterly is reasonable for most teams) and automate the handoff so there's no downtime between old and new keys.
- Revoke immediately on suspicion. If a key appears in a log, a support ticket, a screen-share, or a public repo (even briefly, even if deleted in a follow-up commit — git history still has it), revoke it and issue a new one. Don't wait to confirm abuse first.
- Watch for usage anomalies. A sudden spike in request volume or requests from unexpected regions is often the first sign a key leaked, often before you've traced the source.
This is where a managed layer helps. SubToAPI issues scoped sub_live_... application keys on top of your underlying Claude access, so you can hand a key to a specific app or teammate, see usage per key in the dashboard, and revoke a single key without rotating credentials for your entire team. Combined with team seats, this means you're not passing one shared secret around in Slack messages and personal .env files.
A Minimal Secure Setup
# .env (never committed)
SUBTOAPI_KEY=sub_live_xxxxxxxxxxxxxxxx
// server-side only — never import this file into client code
const apiKey = process.env.SUBTOAPI_KEY;
if (!apiKey) {
throw new Error("SUBTOAPI_KEY is not set");
}
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Summarize this ticket." }],
}),
});
Failing fast with a clear error when the variable is missing (if (!apiKey) throw ...) prevents a more confusing failure mode downstream, and it keeps you from accidentally falling back to a hardcoded default key during testing. See the quickstart and messages docs for the full request shape, and pricing for plan details if you're setting up team-wide access.
Checklist Before You Ship
.envis git-ignored,.env.examplehas placeholders only- No
NEXT_PUBLIC_/VITE_/client-bundle-prefixed key variables - CI secrets are stored in the platform's encrypted vault, masked in logs
- Production secrets come from a secret manager, not a baked-in
.env - Separate keys per environment/service, rotated on a schedule
- A process exists for immediate revocation if a key is exposed
Questions
Is it safe to store a Claude API key in a .env file? Yes, as long as the file is excluded from version control via .gitignore and never shipped into a client-side bundle. .env files are fine for local development and many simple deployments, but production systems should prefer a dedicated secret manager.
What should I do if I accidentally committed an API key to Git? Revoke the key immediately — don't wait to assess impact. Removing the key from a later commit doesn't remove it from git history, so treat the old key as permanently compromised and issue a new one.
Can I use the same Claude API key across dev, staging, and production? You can, but it's not recommended. Separate keys per environment limit the blast radius of a leak and make it much easier to identify which environment generated unexpected usage.