Secrets & Access
An API key, a database password, or a signing token is worth as much to an attacker as the data it unlocks. Most breaches don’t come from a clever exploit; they come from a secret that ended up somewhere it shouldn’t have: a committed .env, a log line, a Slack message. The rules here are about closing that door before it opens.
Secrets never live in code or logs#
- Never commit a secret. Not a real key “just for testing,” not a password in a comment, not a token in a fixture. If it can authenticate as something, it does not belong in a diff.
- Never log a secret. A request log, an error trace, or a debug print that includes an API key or a token turns your observability stack into a second place that secret now lives, one with far looser access control than wherever it was issued from.
- Secrets live in a secrets manager or environment configuration, not the repo. Application code reads a secret from its environment at runtime; it never contains the value itself. If you’re unsure where a secret should be configured for a given service, ask rather than guess.
- If a secret does leak (a commit, a log, a screenshot), rotate it. A secret that has been exposed is compromised the moment it’s exposed, whether or not you can prove anyone used it. Removing it from history is not enough; the value itself has to change.
Least privilege, for people and for services#
Access is granted for a reason, not by default.
| Principle | In practice |
|---|---|
| Scope to the job | A person or a service gets access to what their role actually requires, not the whole system “to be safe” |
| No standing admin by habit | Broad or admin-level access is the exception, granted for a specific need, not the default account setup |
| Services get their own credentials | One service’s key should not double as another’s; a compromise in one place shouldn’t cascade |
| Review, don’t accumulate | Access earned for a past project doesn’t automatically carry forward once that need ends |
This is the same instinct behind gating an initiative on a feature flag rather than shipping it wide open: grant the smallest surface that gets the job done, and widen it deliberately if the need grows.
Rotate on departure#
When someone leaves the team, a client relationship ends, or a contractor’s engagement wraps, their access ends with it, not eventually, immediately.
- Revoke accounts and API access as part of offboarding, not a follow-up task that might happen later.
- Rotate any shared secret that person had access to. A credential someone knew is one you can no longer fully trust once they’re gone.
- The same applies in reverse when someone joins: grant only what their role needs on day one, not a copy of a teammate’s broader access for convenience.
Access is auditable#
If a system or a piece of data matters enough to protect, it matters enough to know who touched it.
- Prefer named, individual credentials over shared logins. “Someone on the team” should never be the honest answer to “who accessed this.”
- Where a system supports an access log, use it. When something goes wrong, especially anything touching the sensitive data described in Security & Data Handling, being able to say precisely who had access and when is the difference between a fast, confident postmortem and a guessing game.
- Treat “we can’t tell who did this” as a gap to close, not a fact of life. If a system genuinely offers no audit trail, that’s worth raising rather than working around quietly.
Practical rules for an engineer#
- Never paste a real secret into a PR, a ticket, or a chat message, even in a private channel. Reference where it lives instead.
- Never widen your own access “just to get unblocked.” Ask for the specific grant you need.
- Treat every
.env.exampleor config template as documentation of what a secret is for, not a place real values ever land. - If you notice access that looks stale or too broad, flag it. Quiet over-access is the same kind of debt as a stale feature flag, it looks harmless until the day it isn’t.
Related: Security & Data Handling, How We Ship, Feature Flags