Secrets Management skill for Claude Code
Rotate first, rewrite history second. When a key leaks, Claude revokes and rotates it before anything else, checks provider audit logs for misuse, and only then offers a confirmed history purge with git filter-repo. For prevention it wires gitleaks into pre-commit and CI, moves secrets into the right store for each environment, and fixes the quiet leaks in Docker layers, client bundles, and logs.
- name
secrets-management - size186 lines · ≈2,150 tokens
- files1
- licenseMIT
- updated
What Claude sees before loading it
This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.
description: Keeps secrets out of code and handles them safely across their lifecycle — gitleaks scanning in pre-commit and CI, .env hygiene, vaults and cloud secret managers, SOPS for encrypted config, rotation, and a step-by-step response when a key leaks. Use when an API key or password appears in code or git history, when setting up secret scanning, choosing where secrets live, rotating credentials, or reviewing env and config handling. Try asking
- I accidentally pushed our AWS keys to GitHub — what do I do right now?
- Set up gitleaks in pre-commit and GitHub Actions for this repo
- Where should our Stripe and database secrets live across dev, CI, and Kubernetes?
Use it when
- A credential appears in code, git history, CI logs, or an image
- Setting up secret scanning for a repo or organization
- Deciding between env files, vaults, SOPS, and cloud secret managers
- Planning credential rotation without downtime
Skip it when
- You need least-privilege permissions for the credentials themselves — use aws-iam instead
- The question is choosing ciphers or key derivation — use cryptography-basics instead
How to check the result
gitleaks reports no findings across history and the working tree, the leaked credential is rejected by the provider, and a test commit containing a fake key is blocked by the hook.
The common mistake it prevents
Spending the first hour rewriting git history while the leaked key stays active, even though scrapers harvest public keys within minutes.
Done well means: no secret ever lands in git, logs, images, or client bundles; every secret has one source of truth, an owner, and a rotation path; and a leaked secret is revoked within minutes, not after a history rewrite debate.
Hard rules
- A secret that reached a remote (pushed commit, CI log, Slack, image layer) is compromised. Revoke and rotate first. Rewriting history is cleanup, never the fix.
- Never print, echo, or paste secret values into chat, logs, or commit messages while working. Refer to them by name and location.
- Never commit
.env; commit.env.examplewith placeholder values only. - Anything bundled for the browser or a mobile app is public.
NEXT_PUBLIC_*,VITE_*,EXPO_PUBLIC_*variables must never hold secrets. - History rewrites and force pushes require explicit user confirmation and coordination with everyone who has a clone.
Workflow: leaked secret response
- [ ] 1. Identify the secret type, scope, and where it leaked
- [ ] 2. Revoke or rotate it at the provider (now)
- [ ] 3. Deploy the new secret to all consumers; confirm the old one fails
- [ ] 4. Check provider audit logs for use between leak and revocation
- [ ] 5. Remove from code; move to a secret store
- [ ] 6. Optionally purge history (with confirmation)
- [ ] 7. Add scanning so it cannot recur; write a short incident note
Step details:
-
Identify. What is it (AWS access key, Stripe live key, DB password, signing key)? What can it do? Where is it exposed (public repo, private repo, CI log, image)? Public exposure means assume automated scrapers already have it — they find keys on public GitHub within minutes.
-
Revoke/rotate. Do it at the provider console or CLI. Examples:
Secret Action AWS access key aws iam create-access-key --user-name X, update consumers,aws iam update-access-key --access-key-id OLD --status Inactive, thenaws iam delete-access-keyGitHub PAT Revoke in Settings > Developer settings; prefer fine-grained tokens or a GitHub App Stripe Roll the key in Dashboard > Developers > API keys (rolling supports an expiry overlap) Database password ALTER ROLE app WITH PASSWORD '...'after creating a second credential or using dual-user rotationJWT/HMAC signing key Add new key (new kid), sign with new, keep old for verify until max token lifetime passes, removeSSH/TLS private key Generate new pair, replace authorized_keys/cert, revoke old cert -
Confirm the old credential is rejected (call the API with it and expect 401/403).
-
Audit. AWS CloudTrail filtered by access key ID, GitHub audit log, Stripe logs, DB connection logs. Escalate to incident-response if there is unexplained use.
-
Remove from code and load from the environment or a secret manager (below).
-
Purge history only after rotation, and only with confirmation:
# Requires git-filter-repo (pip install git-filter-repo). Work on a fresh mirror clone. git clone --mirror [email protected]:org/repo.git && cd repo.git printf 'AKIAOLDKEYVALUE==>REMOVED\n' > ../replacements.txt git filter-repo --replace-text ../replacements.txt # Or drop a whole file from all history: git filter-repo --invert-paths --path config/prod.env # DESTRUCTIVE: confirm with the user before pushing rewritten history git push --force --mirrorThen: ask collaborators to re-clone, and on GitHub contact support to purge cached views of the old commits; forks and existing clones still contain the secret.
-
Prevent (next section) and record: what leaked, when, exposure window, actions.
Prevention: scanning
Default tool: gitleaks (v8). Run it three places.
# Whole history of the current repo
gitleaks git -v --redact
# Working directory or any folder (no git needed)
gitleaks dir . -v --redact
# JSON report for CI artifacts
gitleaks git --redact --report-format json --report-path gitleaks.json
Older docs use gitleaks detect and gitleaks protect; they still work in v8 but git
and dir are the current subcommands.
Pre-commit (with the pre-commit framework):
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.24.2 # pin to the latest release tag you have verified
hooks:
- id: gitleaks
CI (GitHub Actions) — fail the build on findings:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Also enable the platform features: GitHub secret scanning and push protection (free for
public repos; included in GitHub Secret Protection for private), GitLab secret detection.
For verifying whether found credentials are live, trufflehog git file://. --only-verified
checks candidates against provider APIs — run only on repos you own.
False positives: add a .gitleaksignore with the finding fingerprint, or a
# gitleaks:allow comment on the line. Never broaden the allowlist to whole directories
of real config.
Where secrets live
| Situation | Use |
|---|---|
| Local development | .env (gitignored) loaded by the framework or dotenv; or op run --env-file=.env.tpl -- npm run dev with 1Password references |
| CI | The CI secret store (GitHub Actions secrets/environments with required reviewers); prefer OIDC federation to cloud over long-lived keys |
| AWS workloads | IAM roles for compute (no keys at all); AWS Secrets Manager or SSM Parameter Store SecureString for third-party secrets |
| GCP / Azure | Workload identity; Secret Manager / Key Vault |
| Kubernetes | External Secrets Operator syncing from the cloud store; or Sealed Secrets / SOPS for GitOps. Plain Secret objects are base64, not encryption — enable etcd encryption at rest |
| Config committed to git | SOPS with age or a cloud KMS key |
| Many services, dynamic creds | HashiCorp Vault / OpenBao with dynamic DB credentials and short TTLs |
SOPS with age:
age-keygen -o ~/.config/sops/age/keys.txt # prints the public key
sops --encrypt --age age1yourpublickey... secrets.yaml > secrets.enc.yaml
sops --decrypt secrets.enc.yaml # needs the private key
Put creation rules in .sops.yaml so teammates do not pass keys by hand.
Application handling
- Read secrets once at startup into config, validate presence, and fail fast with the variable name (never value) if missing.
- Redact in logs: configure logger redaction (
pinoredactpaths,structlogprocessors) forauthorization,cookie,password,token,secret,api_key. - Do not pass secrets as CLI arguments (visible in
psand shell history); use env or files with0600permissions. - Docker: never
ARG/ENVa secret — it persists in image layers. Use BuildKit secrets:RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ciwithdocker build --secret id=npmrc,src=$HOME/.npmrc .. - Prefer short-lived credentials (OIDC, STS, dynamic DB users) over rotation schedules.
Audit an existing repo
gitleaks git -v --redact # history
gitleaks dir . -v --redact # untracked files too
git ls-files | grep -iE '(^|/)\.env($|\.)|\.pem$|id_rsa|\.p12$|\.pfx$|credentials'
grep -rnE "(NEXT_PUBLIC|VITE|EXPO_PUBLIC)_[A-Z_]*(SECRET|KEY|TOKEN)" --include=*.{ts,tsx,js,env*} .
docker history --no-trunc <image> | grep -iE "secret|token|password|key="
Report each finding as: type, location (file:line or commit), exposure (public/private/ image), live or not, action taken.
Gotchas
- Deleting the file in a new commit leaves the secret in history and in every clone.
.gitignoredoes not untrack files already committed; usegit rm --cached.- CI logs: masked secrets leak when transformed (base64, URL-encoded, split). Never
set -xin steps that handle secrets. - Rotating a key used by many services without a dual-key window causes an outage; support two valid keys during the cutover.
- Terraform state contains secrets in plaintext; store it in an encrypted, access- controlled backend.
Verification
gitleaks gitandgitleaks dir .report no findings (or only documented, fingerprinted false positives).- The leaked credential returns 401/403 when used; the new one works in every consumer.
- Pre-commit and CI scanning are in place; a test commit with a fake AWS-format key is blocked.
About this skill
Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.