Skip to main content
QuantLab Logo

Secrets Management · 2026

Secrets Management Best Practices: A 2026 Guide

A leaked API key is the fastest path to a cloud breach — one credential in a public repo can turn into account takeover, data theft, and a five-figure bill overnight. This is the practitioner's guide to keeping keys, tokens, and credentials where they belong: secrets managers, KMS envelope encryption, rotation, least privilege, and leak detection.

Bill Beltz, Founder & Principal Engineer
By , Founder & Principal EngineerPublished 13 min read

Quick answer

Keep secrets out of source control and client bundles, and store them in a dedicated secrets manager (AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, or HashiCorp Vault) or your platform's encrypted environment variables. Encrypt at rest with KMS envelope encryption, scope every credential to least privilege, prefer short-lived dynamic credentials over long-lived static keys, and rotate on a schedule and on compromise. Detect leaks before they ship with pre-commit scanning and push protection, and when one leaks, revoke first, then rotate, then audit.

Stolen and leaked credentials are consistently the most common single cause of cloud breaches. They do not require a clever exploit chain — a valid key is a valid key, and once it is in the wrong hands the attacker simply logs in. At QUANT LAB USA we treat secrets hygiene as a first-class control on every build, and it is one of the first things we look at on a penetration test. The sections below follow the order that matters in practice: understand the threat, put secrets in the right place, encrypt and rotate them, scope them down, keep your environments clean, and catch leaks before they ship.

1. The threat: a leaked key is a logged-in attacker

A secret is anything that grants access: API keys, database passwords, OAuth client secrets, cloud access keys, signing keys, and tokens. When one leaks, there is no malware to detect and no vulnerability to patch — the credential works exactly as designed, for whoever holds it. That is why credential exposure tops the list of cloud breach causes year after year.

  • Source control is the usual leak vector. Keys get committed by accident, then live forever in git history even after they are deleted from the current file.
  • Bots scan public repos in seconds. A cloud key pushed to a public GitHub repo is routinely exploited within minutes of the push.
  • Blast radius scales with scope. An over-permissioned key turns one leak into a full account takeover; a tightly scoped one limits the damage.

2. Where secrets belong: a dedicated secrets manager

The goal is to keep the secret value out of code entirely and inject it at runtime from a system built for the job. A dedicated secrets manager gives you encryption at rest, access policies, rotation, and an audit log in one place. Use the one native to your platform — AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, or HashiCorp Vault for a cloud-agnostic option — and for a managed host like Vercel or Netlify, the platform's encrypted environment-variable store is an acceptable baseline.

  • Reference secrets by name in your application and resolve them at boot or deploy time, so the value never touches your repository.
  • Never embed a secret in a client-side JavaScript bundle, a single-page app, or a mobile binary — anything shipped to a device is trivially extractable, so a "secret" there is public.
  • Keep a separate store and a separate set of values per environment so development and staging cannot read production secrets.

This is the same discipline we apply when we build a customer-facing platform — see our SaaS platform development practice for how secrets handling fits into the broader architecture.

3. Encryption at rest: KMS and envelope encryption

Storing a secret is not enough; it must be encrypted at rest with a key you control. The standard pattern is envelope encryption: data is encrypted with a data encryption key (DEK), and that DEK is itself encrypted by a key encryption key (KEK) that lives inside a key management service — AWS KMS, GCP Cloud KMS, or Azure Key Vault. The KEK never leaves the KMS, which gives you a hardware-backed root of trust and a clean place to rotate keys and audit access.

  • Rotating the KEK does not require re-encrypting all your data — you only re-wrap the DEKs, which is why this model scales.
  • Every major secrets manager uses KMS under the hood; enabling customer-managed keys gives you control over the rotation schedule and an audit trail of decrypt calls.
  • Follow NIST SP 800-57 for key lifecycle guidance: generation, distribution, rotation, and destruction.

4. Rotation, least privilege, and short-lived credentials

The longer a credential lives and the more it can do, the worse a leak hurts. Two controls fix this: rotate often, and grant little. Rotate long-lived secrets on a schedule — typically every 30 to 90 days for high-value credentials — and rotate immediately on any suspicion of compromise. Where the platform supports it, turn on automated rotation so it actually happens.

The bigger leap is to stop using long-lived static keys wherever you can. Short-lived, dynamically issued credentials expire on their own, so a leaked token is dead within minutes to hours. Vault's dynamic secrets generate a unique, time-bound credential per request — for example, a database login that is created on read and revoked at the end of its lease:

# Vault issues a fresh, short-lived DB credential on demand
$ vault read database/creds/readonly
Key                Value
---                -----
lease_id           database/creds/readonly/abc123
lease_duration     1h        # auto-revoked when the lease expires
username           v-token-readonly-x9f2     # unique per request
password           A1a-2Bb3Cc4Dd5Ee...       # never reused, never stored
  • Scope every credential to least privilege — the minimum permissions and the narrowest resources it needs, nothing more.
  • Prefer short-lived tokens and instance/workload identity over static keys for service-to-service access.
  • Keep an inventory of every long-lived key that still exists; each one is a standing liability and a rotation obligation.

5. Environment hygiene: never commit a secret

Most leaks are mundane: a developer adds a key to a .env file and commits it. A local .env is fine for development as long as it is git-ignored, but it is plaintext, has no access policy, and does not belong in production. The first line of defense is making it impossible to commit by accident:

# .gitignore — keep every secret-bearing file out of git
.env
.env.*
!.env.example        # commit a placeholder template, never real values
*.pem
*.key
secrets/
credentials.json
  • Commit a .env.example with empty placeholders so teammates know which variables exist without seeing real values.
  • Use a separate set of secrets per environment — development, staging, and production should share no credentials.
  • In production, pull from a secrets manager or the platform's encrypted variable store; do not ship a .env file in a Docker image.
  • Remember that anything in a client bundle or mobile app is public — keep server-only secrets on the server.

6. Leak detection and CI/CD: catch it before it ships

Hygiene fails sometimes, so add automated detection. Run a secret scanner like gitleaks or trufflehog as a pre-commit hook and again in CI, and enable your host's secret scanning and push protection so a commit containing a recognizable key is blocked before it ever reaches the remote. For the pipeline itself, eliminate the secret entirely: replace long-lived cloud keys with OIDC federation, where your CI run presents a signed identity token and the cloud mints a short-lived, scoped credential in exchange.

# GitHub Actions: assume an AWS role via OIDC — no static keys stored
permissions:
  id-token: write        # let the runner request an OIDC token
  contents: read
steps:
  - uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123456789012:role/deploy
      aws-region: us-east-1
      # the role trusts token.actions.githubusercontent.com,
      # scoped to this repo + branch — nothing secret lives in the repo

When a secret does leak, the response order is non-negotiable: revoke, rotate, audit.

# 1) REVOKE first — kill the leaked credential at the provider
aws iam delete-access-key --access-key-id AKIA... --user-name ci-bot

# 2) ROTATE — issue a fresh value and store it in the secrets manager
aws iam create-access-key --user-name ci-bot
aws secretsmanager put-secret-value --secret-id ci-bot-key --secret-string ...

# 3) AUDIT — review what the exposed key actually did
#    (CloudTrail / access logs), then scrub it from git history

Revoking first is the part teams get wrong — they rush to delete the commit while the live key keeps working. Make the credential useless before you tidy the repository. The same blocking-the-leak-first instinct shows up in API security best practices and in how we verify inbound Stripe webhook signatures.

Mid-post: find the secrets you forgot about

Most teams have a long-lived key in a repo, a CI log, or a Slack message they have forgotten about. A security review finds the exposed credentials and the over-permissioned keys before an attacker does. Book a free scoping call.

Where to store what

Secret typeWhere it belongs
Cloud access keysReplace with workload identity / OIDC; if unavoidable, a secrets manager with rotation
Database credentialsDynamic, short-lived credentials (Vault) or a secrets manager with scheduled rotation
Third-party API keysSecrets manager or platform env vars; scoped to least privilege, never in the client
Signing / encryption keysKMS / HSM — the key material never leaves the service
Local dev secretsGit-ignored .env; distinct values, never production credentials
Anything client-sideNo secrets — bundles and mobile apps are public; proxy through your server

For the broader risk landscape these controls map to, see the OWASP Top 10 explained.

Operational practices that hold over time

Tools without process decay. Three habits keep secrets under control past launch day:

  • Inventory and ownership. Know every secret that exists, where it lives, and who owns its rotation. Unknown credentials are the ones that leak.
  • Audit the access logs. A secrets manager records every read; alert on unusual access and review it during incidents.
  • Bake it into compliance cadence. Secrets management is an explicit control in most frameworks — see how to prepare for a SOC 2 audit and our cybersecurity guide for SaaS startups.

Frequently asked questions

Where should I store API keys and secrets?

Store them in a dedicated secrets manager — AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, or HashiCorp Vault — or in platform-provided environment variables for a managed host like Vercel. The secret should be injected into the running process at deploy or boot time, never hardcoded into source and never baked into a client bundle or mobile binary. A real secrets manager gives you encryption at rest, fine-grained access policies, automatic rotation, and an audit trail of who read what. That combination is the baseline; a config file with credentials in it is not.

How often should secrets be rotated?

Rotate long-lived secrets on a fixed schedule — commonly every 30 to 90 days for high-value credentials — and rotate immediately on any suspicion of compromise. The bigger win is to stop relying on long-lived static keys at all: short-lived, automatically issued credentials expire on their own, so a leaked token is useless within minutes to hours. Where you must keep static keys, automate the rotation so it actually happens instead of becoming a calendar task everyone ignores. Treat the day a key leaks as the day it must be revoked, not the day it is scheduled to rotate.

What should I do when a secret leaks?

Revoke first, then rotate, then audit. Revoking the credential at the provider immediately makes the leaked value useless, which matters more than tidying up the repository. Issue a fresh credential, deploy it, and confirm the old one is dead. Only then go back and scrub the secret from git history, CI logs, screenshots, and anywhere else it spread. Finally, review access logs for the exposed credential to determine whether it was actually used and what it touched, and feed that into your incident timeline.

Is it safe to put secrets in a .env file?

A local .env file is fine for development as long as it is listed in .gitignore and never committed. The danger is that .env files routinely leak into version control, Docker images, CI logs, and backups. They are plaintext, hold no access policy, and offer no rotation or audit trail, so they do not belong in production. In deployed environments, pull secrets from a secrets manager or the platform's encrypted environment-variable store instead, and keep a separate set of secrets per environment so a development leak cannot touch production.

What is envelope encryption, and why does it matter?

Envelope encryption means you encrypt your data with a data encryption key (DEK), then encrypt that DEK with a separate key encryption key (KEK) held in a key management service like AWS KMS, GCP Cloud KMS, or Azure Key Vault. The KEK never leaves the KMS, so rotating it or revoking access does not require re-encrypting all of your data. It is the standard model behind encryption at rest in every major cloud, and it gives you a hardware-backed root of trust plus a clean audit boundary. For most teams, the practical upshot is enabling KMS-backed encryption and letting the managed service handle the key hierarchy.

How do I keep secrets out of my CI/CD pipeline and cloud deploys?

Replace long-lived cloud access keys with OIDC federation. Your CI provider — GitHub Actions, GitLab, or similar — issues a signed identity token for each run, and your cloud trusts that token to mint short-lived credentials scoped to exactly what the job needs. Nothing static is stored in the pipeline, so there is no key to leak or rotate. Pair that with masked secret stores for anything that genuinely must be a static value, restrict which branches and environments can assume privileged roles, and never echo secrets into build logs.

Lock down your secrets before someone finds them.

A security review surfaces the exposed keys, the over-permissioned credentials, and the rotation gaps that turn one mistake into a breach. Book a free scoping call and we'll cover the right depth for your stack.

Or call Bill directly at (770) 652-1282
All blog postsUpdated June 17, 2026