How to keep secrets out of your code
Updated 7 November 2026 · 6 min read
A secret in source code is any value that grants access: API keys, database passwords, private keys, signing secrets, OAuth client secrets. Once one is committed, everyone who can read the repository can use it, and so can anyone who gets a copy later. Deleting the line doesn’t help, because git keeps the old version.
AI coding agents make this more common, not less. Ask one to “connect to Stripe” and it may paste the key you showed it straight into a file.
Why it matters for audits
Secrets in code show up in almost every security review. SOC 2 (CC6.1, logical access) and ISO 27001 (A.8.24, use of cryptography, and the access controls around it) both expect keys to be controlled, limited and changeable. A key in a repository is none of those. It is also one of the first things a customer’s security questionnaire asks about.
How they get in
// 1. Pasted directly
export const stripeKey = "sk_live_...";
// 2. A config file committed by accident
// .env, config/production.json, serviceAccount.json
// 3. A test or script that "just needs it for now"
const db = new Client({ password: "hunter2" });
// 4. A private key file
// id_rsa, server.key, *.pem
If one has already leaked
Do these in order. The first one matters most.
- Rotate the secret. Create a new key in the provider’s dashboard and revoke the old one. Until you do, assume someone has it.
- Check the provider’s logs for use you don’t recognise since the commit date.
- Move the new value out of the code using one of the methods below.
- Clean the history if you need to. Tools such as
git filter-repocan remove a file or string from every commit. This rewrites history, so coordinate with everyone who has a copy. If the repository was ever public, rotating is what protects you; cleaning history doesn’t recall copies that were already made.
How to keep them out
Environment variables
Read secrets from the environment at runtime, and keep local values in a .env file that is never committed.
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
.env
.env.*
!.env.example
Commit a .env.example with the variable names and empty values, so new developers know what to set.
A secret manager
For production, store secrets in your platform’s secret store instead of plain environment files: for example GitHub Actions secrets, Cloudflare or Vercel environment secrets, AWS Secrets Manager, Google Secret Manager or HashiCorp Vault. These keep an access history and make rotation easier, which is exactly what an auditor asks about.
Checks before code lands
- A pre-commit hook with a secret scanner, such as gitleaks, stops a commit that contains something that looks like a key.
- GitHub’s secret scanning and push protection block many known key formats on push.
- A check in CI catches what slipped past a laptop.
Short-lived credentials
Where the platform supports it, prefer credentials that expire, such as OIDC tokens from your CI to your cloud account, over long-lived keys. A leaked token that expires in an hour does far less damage.
What Lintsure checks
The secret or private key committed to source rule looks for well-known key formats in code and config files, including .env, JSON, YAML and TOML files inside the scanned folder: Stripe live keys, AWS access key IDs, GitHub and Slack tokens, and private key blocks. It marks them as a Gap and suggests moving the value to an environment variable or a secret manager.
It doesn’t catch every secret. A plain password string like the one in example 3 has no recognisable format, so pair Lintsure with a dedicated secret scanner and code review.
Through a coding agent, Lintsure proposes the change and waits for your approval. It can’t rotate the key for you, and rotating is the step that actually closes the risk.
Check your own code
Lintsure runs these checks on your machine and never uploads your code.
npx lintsure scanThis guide is our own reading of public texts, written for software teams. It is not legal advice and it doesn't cover your whole obligation, only the parts code can show. Ask a qualified person before any audit or decision. Disclaimer