Use when you need to review or design secret and configuration handling — secret managers (Vault, AWS Secrets Manager, SSM, GCP/Azure), rotation, runtime injection, keeping secrets out of IaC and images, sealed/external secrets, and config-vs-secret separation.
Review and design how an application and its infrastructure handle secrets and configuration — selecting a secret manager (Vault, AWS Secrets Manager, SSM Parameter Store, GCP Secret Manager, Azure Key Vault), defining rotation, injecting secrets at runtime rather than baking them into images or IaC, separating non-sensitive config from secrets, and using sealed/external secrets in Kubernetes. The goal is that no secret ever lives in source, IaC state, container layers, or logs, that every secret is rotatable, and that access is least-privilege and audited. Ground findings in the repo's actual files and manifests.
When to use
A PR introduces credentials, API keys, tokens, connection strings, or certificates.
A secret manager needs to be chosen or its access pattern reviewed.
Secrets are suspected in source, .env, IaC, container images, or CI logs.
Rotation is missing, manual, or unknown for a credential.
Kubernetes secret handling needs review (plaintext Secret vs sealed/external secrets).
A config system mixes secrets and non-secret settings without separation.
When not to use
The task is broad application env-config typing with no secret/security dimension — a lighter config review fits.
The repo has no secrets and no infrastructure that consumes them.
A full authorization/permission model review is needed — pair with the authz review skill.
Procedure
1. Scan the repo for leaked secrets
# High-signal patterns across the tree (exclude vendored/build dirs)
grep -rniE "(api[_-]?key|secret|password|token|passwd|private[_-]?key|client[_-]?secret)\s*[:=]\s*['\"][^'\"$]{6,}" \
. --include="*.*" 2>/dev/null | grep -vE "example|sample|test|\.lock|node_modules" | head -40
# Provider key shapes (AWS access key id, private key blocks)
grep -rnE "AKIA[0-9A-Z]{16}|-----BEGIN [A-Z ]*PRIVATE KEY-----" . 2>/dev/null | head
# Dedicated scanners if available
gitleaks detect --no-banner 2>/dev/null || trufflehog filesystem . 2>/dev/null | tail -20
2. Check that secrets are gitignored and not in history
# Which secret backend is referenced?
grep -rniE "secretsmanager|ssm|parameter store|vault|key.?vault|secret.?manager|sealed.?secret|external.?secret" . --include="*.tf" --include="*.yaml" --include="*.y*ml" | head
# How does the app read config/secrets at runtime?
grep -rnE "os\.environ|process\.env|getenv|System\.getenv|Environment\.GetEnvironmentVariable" . 2>/dev/null | head
4. Verify secrets are not baked into IaC or images
# Plaintext secret values in IaC / vars
grep -rnE "(password|secret|token|key)\s*=\s*\"[^\"$]" . --include="*.tf" --include="*.tfvars" | grep -v "secretsmanager\|ssm\|vault\|data\." | head
# Secrets baked into Docker layers
grep -rnE "ARG .*(SECRET|TOKEN|PASSWORD|KEY)|ENV .*(SECRET|TOKEN|PASSWORD)|COPY .*(\.env|\.pem|credentials)" . --include="Dockerfile*"
# Rotation hooks (Secrets Manager rotation lambda, Vault TTL/lease, dynamic secrets)
grep -rniE "rotation|rotate|lease|ttl|max_ttl" . --include="*.tf" --include="*.hcl" | head
# Non-secret config should live separately from secrets (configmaps / settings vs secret refs)
grep -rln "kind: ConfigMap" . --include="*.yaml"
Concrete checks
No secret value appears in source, .tfvars, manifests, Dockerfiles, or committed .env files.
.env, *.pem, credentials, and secret YAML/JSON are gitignored and absent from git history.
A secret manager (Vault/Secrets Manager/SSM/Key Vault/GCP) is the source of truth for secrets.
Secrets are injected at runtime (env from secret ref, mounted file, or sidecar), not at build time.
IaC references secrets by ARN/path/data source — it never stores the plaintext value.
Kubernetes uses SealedSecrets or an ExternalSecrets operator instead of committing plaintext Secrets.
Every secret has a defined rotation policy (automatic rotation, short-lived/dynamic, or scheduled).
Access to each secret is least-privilege (scoped IAM/policy/Vault role), not broad read-all.
Secret access is audited/logged by the manager.
Non-secret configuration is separated from secrets (ConfigMap/settings vs secret store).
Secrets are never logged; logging redacts known secret keys.
CI/CD pulls secrets from a vault/OIDC at run time, not from committed files or plaintext variables.
Commands or Templates
# Terraform: reference a secret, never store its value
data "aws_secretsmanager_secret_version" "db" {
secret_id = "prod/db/password" # value lives in Secrets Manager
}
resource "aws_db_instance" "primary" {
username = "app"
password = data.aws_secretsmanager_secret_version.db.secret_string # not hardcoded
}
# Scoped read policy — least privilege to ONE secret
data "aws_iam_policy_document" "read_db_secret" {
statement {
actions = ["secretsmanager:GetSecretValue"]
resources = [aws_secretsmanager_secret.db.arn] # not "*"
}
}
# Kubernetes: ExternalSecret pulls from the manager into a native Secret at runtime
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata: { name: api-secrets, namespace: prod }
spec:
refreshInterval: 1h
secretStoreRef: { name: aws-secrets, kind: SecretStore }
target: { name: api-secrets }
data:
- secretKey: DB_PASSWORD
remoteRef: { key: prod/db/password }
# Safe detection only — never print the secret value
gitleaks detect --no-banner --redact # redacts matches in output
aws secretsmanager describe-secret --secret-id prod/db/password # metadata, not value
Common issues & anti-patterns
Secrets committed in .env, config.json, or .tfvars — and still present in git history after "removal".
Plaintext password in a *.tf file or a Kubernetes Secret manifest (base64 is not encryption).
Secrets passed as Docker build ARG/ENV — permanently embedded in image history.
One static credential shared by every service and never rotated.
A single broad policy granting secretsmanager:GetSecretValue on *.
Mixing secrets into ConfigMaps or non-secret settings files.
Logging full request/connection objects that include credentials.
CI storing long-lived cloud keys as plaintext variables instead of using OIDC/short-lived tokens.
Required output
Produce a structured report with:
Leak scan — any secrets found in source/IaC/images/history (redacted), with file:line.
Storage — which secret manager is used and what is still stored outside it.
Injection — runtime vs build-time injection path per secret consumer.
Kubernetes — plaintext Secrets vs sealed/external secrets status.
Rotation — rotation policy (or its absence) per secret.
Access — least-privilege review of secret-read policies.
Config separation — secrets vs non-secret config mixing.
Findings table + next safe action — file:line | issue | severity | fix, then the top remediation.
Safety
This is a review and design skill. NEVER print, echo, or log a real secret value; always redact to ****. Use scanner --redact flags and read only secret metadata, never the value, unless a human explicitly requests it.
NEVER create, overwrite, rotate, or delete secrets in a live manager (aws secretsmanager put/delete, vault write, kubectl create secret) without explicit human approval.
Treat any secret found in source or git history as compromised — flag it for immediate rotation and removal from history; do not assume removing the file is sufficient.
Do not commit any file containing a real secret; do not move secrets between systems without approval.
Recommend rotation and least-privilege scoping; do not apply IAM/policy changes to a live account unattended.
Do not disable audit logging on a secret manager.
1---2name: secrets-and-config-management3description: Use when you need to review or design secret and configuration handling — secret managers (Vault, AWS Secrets Manager, SSM, GCP/Azure), rotation, runtime injection, keeping secrets out of IaC and images, sealed/external secrets, and config-vs-secret separation.4---56# Secrets & Config Management78## Purpose910Review and design how an application and its infrastructure handle secrets and configuration — selecting a secret manager (Vault, AWS Secrets Manager, SSM Parameter Store, GCP Secret Manager, Azure Key Vault), defining rotation, injecting secrets at runtime rather than baking them into images or IaC, separating non-sensitive config from secrets, and using sealed/external secrets in Kubernetes. The goal is that no secret ever lives in source, IaC state, container layers, or logs, that every secret is rotatable, and that access is least-privilege and audited. Ground findings in the repo's actual files and manifests.1112## When to use1314- A PR introduces credentials, API keys, tokens, connection strings, or certificates.15- A secret manager needs to be chosen or its access pattern reviewed.16- Secrets are suspected in source, `.env`, IaC, container images, or CI logs.17- Rotation is missing, manual, or unknown for a credential.18- Kubernetes secret handling needs review (plaintext `Secret` vs sealed/external secrets).19- A config system mixes secrets and non-secret settings without separation.2021## When not to use2223- The task is broad application env-config typing with no secret/security dimension — a lighter config review fits.24- The repo has no secrets and no infrastructure that consumes them.25- A full authorization/permission model review is needed — pair with the authz review skill.2627## Procedure2829### 1. Scan the repo for leaked secrets3031```bash32# High-signal patterns across the tree (exclude vendored/build dirs)33grep -rniE "(api[_-]?key|secret|password|token|passwd|private[_-]?key|client[_-]?secret)\s*[:=]\s*['\"][^'\"$]{6,}" \34 . --include="*.*" 2>/dev/null | grep -vE "example|sample|test|\.lock|node_modules" | head -4035# Provider key shapes (AWS access key id, private key blocks)36grep -rnE "AKIA[0-9A-Z]{16}|-----BEGIN [A-Z ]*PRIVATE KEY-----" . 2>/dev/null | head37# Dedicated scanners if available38gitleaks detect --no-banner 2>/dev/null || trufflehog filesystem . 2>/dev/null | tail -2039```4041### 2. Check that secrets are gitignored and not in history4243```bash44git ls-files | grep -E "\.env$|\.env\.|secrets?\.(ya?ml|json)|\.pem$|credentials$" && echo "TRACKED SECRET FILES — CRITICAL"45grep -E "\.env|secrets|\.pem|credentials" .gitignore 2>/dev/null || echo "secret files not gitignored"46```4748### 3. Identify the secret manager and injection path4950```bash51# Which secret backend is referenced?52grep -rniE "secretsmanager|ssm|parameter store|vault|key.?vault|secret.?manager|sealed.?secret|external.?secret" . --include="*.tf" --include="*.yaml" --include="*.y*ml" | head53# How does the app read config/secrets at runtime?54grep -rnE "os\.environ|process\.env|getenv|System\.getenv|Environment\.GetEnvironmentVariable" . 2>/dev/null | head55```5657### 4. Verify secrets are not baked into IaC or images5859```bash60# Plaintext secret values in IaC / vars61grep -rnE "(password|secret|token|key)\s*=\s*\"[^\"$]" . --include="*.tf" --include="*.tfvars" | grep -v "secretsmanager\|ssm\|vault\|data\." | head62# Secrets baked into Docker layers63grep -rnE "ARG .*(SECRET|TOKEN|PASSWORD|KEY)|ENV .*(SECRET|TOKEN|PASSWORD)|COPY .*(\.env|\.pem|credentials)" . --include="Dockerfile*"64```6566### 5. Review Kubernetes secret handling6768```bash69# Plaintext Secret manifests vs sealed/external secrets70grep -rn "kind: Secret" -A4 . --include="*.yaml" | grep -i "stringData\|data:"71grep -rln "kind: SealedSecret\|kind: ExternalSecret\|kind: SecretStore" . --include="*.yaml"72```7374### 6. Confirm rotation and config/secret separation7576```bash77# Rotation hooks (Secrets Manager rotation lambda, Vault TTL/lease, dynamic secrets)78grep -rniE "rotation|rotate|lease|ttl|max_ttl" . --include="*.tf" --include="*.hcl" | head79# Non-secret config should live separately from secrets (configmaps / settings vs secret refs)80grep -rln "kind: ConfigMap" . --include="*.yaml"81```8283## Concrete checks8485- [ ] No secret value appears in source, `.tfvars`, manifests, Dockerfiles, or committed `.env` files.86- [ ] `.env`, `*.pem`, `credentials`, and secret YAML/JSON are gitignored and absent from git history.87- [ ] A secret manager (Vault/Secrets Manager/SSM/Key Vault/GCP) is the source of truth for secrets.88- [ ] Secrets are injected at runtime (env from secret ref, mounted file, or sidecar), not at build time.89- [ ] IaC references secrets by ARN/path/data source — it never stores the plaintext value.90- [ ] Kubernetes uses SealedSecrets or an ExternalSecrets operator instead of committing plaintext `Secret`s.91- [ ] Every secret has a defined rotation policy (automatic rotation, short-lived/dynamic, or scheduled).92- [ ] Access to each secret is least-privilege (scoped IAM/policy/Vault role), not broad read-all.93- [ ] Secret access is audited/logged by the manager.94- [ ] Non-secret configuration is separated from secrets (ConfigMap/settings vs secret store).95- [ ] Secrets are never logged; logging redacts known secret keys.96- [ ] CI/CD pulls secrets from a vault/OIDC at run time, not from committed files or plaintext variables.9798## Commands or Templates99100```hcl101# Terraform: reference a secret, never store its value102data "aws_secretsmanager_secret_version" "db" {103 secret_id = "prod/db/password" # value lives in Secrets Manager104}105106resource "aws_db_instance" "primary" {107 username = "app"108 password = data.aws_secretsmanager_secret_version.db.secret_string # not hardcoded109}110111# Scoped read policy — least privilege to ONE secret112data "aws_iam_policy_document" "read_db_secret" {113 statement {114 actions = ["secretsmanager:GetSecretValue"]115 resources = [aws_secretsmanager_secret.db.arn] # not "*"116 }117}118```119120```yaml121# Kubernetes: ExternalSecret pulls from the manager into a native Secret at runtime122apiVersion: external-secrets.io/v1beta1123kind: ExternalSecret124metadata: { name: api-secrets, namespace: prod }125spec:126 refreshInterval: 1h127 secretStoreRef: { name: aws-secrets, kind: SecretStore }128 target: { name: api-secrets }129 data:130 - secretKey: DB_PASSWORD131 remoteRef: { key: prod/db/password }132```133134```bash135# Safe detection only — never print the secret value136gitleaks detect --no-banner --redact # redacts matches in output137aws secretsmanager describe-secret --secret-id prod/db/password # metadata, not value138```139140## Common issues & anti-patterns141142- Secrets committed in `.env`, `config.json`, or `.tfvars` — and still present in git history after "removal".143- Plaintext password in a `*.tf` file or a Kubernetes `Secret` manifest (base64 is not encryption).144- Secrets passed as Docker build `ARG`/`ENV` — permanently embedded in image history.145- One static credential shared by every service and never rotated.146- A single broad policy granting `secretsmanager:GetSecretValue` on `*`.147- Mixing secrets into ConfigMaps or non-secret settings files.148- Logging full request/connection objects that include credentials.149- CI storing long-lived cloud keys as plaintext variables instead of using OIDC/short-lived tokens.150151## Required output152153Produce a structured report with:1541. **Leak scan** — any secrets found in source/IaC/images/history (redacted), with file:line.1552. **Storage** — which secret manager is used and what is still stored outside it.1563. **Injection** — runtime vs build-time injection path per secret consumer.1574. **Kubernetes** — plaintext Secrets vs sealed/external secrets status.1585. **Rotation** — rotation policy (or its absence) per secret.1596. **Access** — least-privilege review of secret-read policies.1607. **Config separation** — secrets vs non-secret config mixing.1618. **Findings table + next safe action** — `file:line | issue | severity | fix`, then the top remediation.162163## Safety164165- This is a review and design skill. NEVER print, echo, or log a real secret value; always redact to `****`. Use scanner `--redact` flags and read only secret *metadata*, never the value, unless a human explicitly requests it.166- NEVER create, overwrite, rotate, or delete secrets in a live manager (`aws secretsmanager put/delete`, `vault write`, `kubectl create secret`) without explicit human approval.167- Treat any secret found in source or git history as compromised — flag it for immediate rotation and removal from history; do not assume removing the file is sufficient.168- Do not commit any file containing a real secret; do not move secrets between systems without approval.169- Recommend rotation and least-privilege scoping; do not apply IAM/policy changes to a live account unattended.170- Do not disable audit logging on a secret manager.
Run npx skillmds@latest add fluxonlab/secrets-and-config-management in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Use when you need to review or design secret and configuration handling — secret managers (Vault, AWS Secrets Manager, SSM, GCP/Azure), rotation, runtime injection, keeping secrets out of IaC and images, sealed/external secrets, and config-vs-secret separation. It is listed under DevOps & Infra on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
FluxonLab (@fluxonlab) published this skill. Their other Agent Skills are listed on their SkillMD profile.