Skip to content
- Secrets never live in source code, commit history, container images, or CI logs — not even in a “private” repository.
- Every secret has an owner, a known set of consumers, and ideally an expiry or rotation schedule.
- Prefer no secret at all (workload identity, short-lived tokens) over a long-lived static secret.
- Local development:
.env files that are git-ignored, or a local secrets tool. Never commit .env files with real values — commit an .env.example with placeholder keys instead.
- CI/CD: the pipeline’s native secrets store (e.g. GitHub Actions secrets), injected as environment variables at run time, not baked into the repository or image.
- Runtime: a dedicated secrets manager or the platform’s environment variable injection, not configuration files checked into the deployment artifact.
- Rotate/revoke the secret immediately — don’t wait to first assess impact.
- Assume it was compromised the moment it became visible (public repo, log output, screen share), regardless of how briefly.
- Purge it from git history if it was committed (rotation still comes first; history rewriting is cleanup, not the fix).
- Note what happened so the root cause (e.g. missing pre-commit hook, overly broad CI log) can be addressed.
- Enable secret scanning on every repository (e.g. GitHub secret scanning / push protection, gitleaks in CI).
- Use pre-commit hooks to catch obvious secrets before they’re pushed.
- Scope secrets as narrowly as possible — a token that can only read one resource is safer than an org-wide admin key.