Secrets Management: Keeping Credentials Out of Your Code
Key takeaway
Secrets belong in a managed secret store, injected at runtime, scoped per environment, and rotated on a schedule. A credential committed to a repository must be treated as compromised and rotated — deleting the commit does not unpublish it.
Almost every application needs database passwords, API keys, and signing keys. Where those live is one of the most consequential and least discussed decisions in a codebase.
Why the common approaches fail
- Hardcoded in source — visible to everyone with repository access, forever, including after they leave.
- Committed .env files — the same problem with an extra step, and they spread through forks and backups.
- Configuration files on servers — better, but nobody knows which server holds which value, and rotation becomes a manual hunt.
- Shared through chat or a password manager by hand — no audit trail, no rotation, and a copy in everyone's message history.
What good looks like
- A managed secret store (cloud provider's own, or a dedicated vault) as the single source.
- Secrets injected at runtime as environment variables or fetched at startup — never baked into a build artifact or container image.
- Separate values per environment, with production accessible to the fewest people possible.
- Access controlled by role, with every read logged.
- Scheduled rotation, with the application able to pick up a new value without a code change.
Prevent the leak at the door
- Run secret scanning in CI and as a pre-commit hook; catching a key before it's pushed saves a rotation.
- Add .env and credential file patterns to .gitignore in the project template, not after the first incident.
- Prefer short-lived credentials and workload identity over long-lived keys wherever the platform supports it.
- Never log configuration objects wholesale — secrets end up in log aggregation, which is often more widely readable than the repository.
When one leaks
Rotate first and investigate second. Rewriting git history does not help: the value may already be cloned, cached, or indexed. Then check the access logs for the affected service over the exposure window, and work out how it got there so the same route closes. Treat every leaked credential as used until you have evidence otherwise.