secrets-management

v2026.09.24

Secrets and credentials management. Covers environment variables, secret stores, rotation policies, and detection of leaked secrets. USE WHEN: user mentions "secrets", "credentials", "API keys", "environment variables", ".env", asks about "secret leaks", "vault", "secret rotation", "gitleaks", "secret detection" DO NOT USE FOR: OWASP vulnerabilities - use `owasp-top-10`, supply chain - use `supply-chain`, general security - use `owasp`

GitHub
Install command
npx skhub add claude-dev-suite/secrets-management
Markdown
SKILL.md

Secrets Management

Golden Rules

  1. Never commit secrets to version control
  2. Never log secrets in application logs
  3. Rotate secrets regularly
  4. Use least privilege for access
  5. Encrypt at rest and in transit

When NOT to Use This Skill

  • JWT/OAuth implementation - Use authentication skills for protocol setup
  • Database security - Use database skills for connection security
  • General OWASP issues - Use owasp-top-10 for broader security
  • Dependency vulnerabilities - Use supply-chain for package security

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: security for comprehensive documentation.

Environment Variables

.env Files

# .env (never commit!)
DATABASE_URL=postgresql://user:pass@localhost:5432/db
API_KEY=sk-xxx
JWT_SECRET=super-secret-key

# .env.example (commit this - no real values)
DATABASE_URL=postgresql://user:pass@host:5432/db
API_KEY=your-api-key-here
JWT_SECRET=generate-a-secure-secret

.gitignore

# Secrets - ALWAYS ignore
.env
.env.local
.env.*.local
*.pem
*.key
credentials.json
secrets.yaml

Loading in Code

// Node.js with dotenv
import 'dotenv/config';
const apiKey = process.env.API_KEY;

// Validate required vars at startup
const required = ['DATABASE_URL', 'API_KEY', 'JWT_SECRET'];
for (const key of required) {
  if (!process.env[key]) {
    throw new Error(`Missing required env var: ${key}`);
  }
}

Secret Detection

Pre-commit Hooks

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

  - repo: https://github.com/Yelp/detect-secrets
    rev: v1.4.0
    hooks:
      - id: detect-secrets
        args: ['--baseline', '.secrets.baseline']

Scanning Commands

# Gitleaks - scan entire history
gitleaks detect --source . --verbose

# Scan only staged changes
gitleaks protect --staged

# TruffleHog
trufflehog git file://. --only-verified

# GitHub secret scanning (in repo settings)
# Enable "Secret scanning" and "Push protection"

Secret Stores

HashiCorp Vault

import Vault from 'node-vault';

const vault = Vault({
  apiVersion: 'v1',
  endpoint: process.env.VAULT_ADDR,
  token: process.env.VAULT_TOKEN
});

const { data } = await vault.read('secret/data/myapp');
const dbPassword = data.data.db_password;

AWS Secrets Manager

import { SecretsManager } from '@aws-sdk/client-secrets-manager';

const client = new SecretsManager({ region: 'us-east-1' });
const response = await client.getSecretValue({ SecretId: 'myapp/db' });
const secret = JSON.parse(response.SecretString!);

Environment-based (Simpler)

// For smaller projects, use encrypted env vars in CI/CD
// GitHub Actions, GitLab CI, etc. all support this

// GitHub Actions
// Settings > Secrets and variables > Actions > New secret

CI/CD Secrets

GitHub Actions

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          # Secrets available as env vars
          ./deploy.sh

      # NEVER do this:
      # - run: echo ${{ secrets.API_KEY }}

Docker

# Never bake secrets into images
# Wrong:
ENV API_KEY=secret

# Right: pass at runtime
# docker run -e API_KEY=$API_KEY myimage
# docker-compose.yml
services:
  app:
    environment:
      - DATABASE_URL  # From shell env
    env_file:
      - .env  # From file (not committed)

Secret Rotation

Policy

Secret TypeRotation Frequency
API keys90 days
Database passwords90 days
JWT secrets180 days
Service accounts365 days
After compromiseImmediately

Rotation Process

  1. Generate new secret
  2. Update in secret store
  3. Deploy new secret to services
  4. Verify functionality
  5. Revoke old secret
  6. Update documentation

Detecting Leaked Secrets

If a secret is leaked:

  1. Revoke immediately - Don't wait
  2. Rotate - Generate new credentials
  3. Audit - Check for unauthorized access
  4. Clean history - Use BFG or git-filter-repo
  5. Post-mortem - Document and prevent recurrence
# Remove from git history (use BFG)
bfg --replace-text passwords.txt repo.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive

Security Checklist

  • .env files in .gitignore
  • .env.example with dummy values committed
  • Pre-commit hooks for secret detection
  • CI/CD secrets in encrypted store
  • No secrets in Docker images
  • Rotation policy defined
  • Least privilege access
  • GitHub secret scanning enabled

Common Secret Patterns

# AWS
AKIA[0-9A-Z]{16}
aws_secret_access_key\s*=\s*.+

# GitHub
ghp_[a-zA-Z0-9]{36}
github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}

# Generic
password\s*=\s*.+
api[_-]?key\s*=\s*.+
secret\s*=\s*.+
token\s*=\s*.+

Anti-Patterns

Anti-PatternWhy It's BadCorrect Approach
Hardcoding API keys in codeExposed in git historyUse .env + .gitignore
Committing .env to repoPublic credential exposureOnly commit .env.example
Using same secret everywhereSingle breach compromises allUse unique secrets per environment
Never rotating secretsStale credentials vulnerableRotate every 90 days minimum
Logging full request/responseMay contain auth tokensSanitize logs before writing
Storing secrets in frontendVisible to all usersBackend only, pass via secure APIs

Quick Troubleshooting

IssueLikely CauseSolution
App can't find env var.env not loaded or wrong nameCheck dotenv is loaded, verify var name
Secret leaked in gitCommitted before .gitignoreUse BFG to clean history, rotate secret
CI/CD can't access secretsNot configured in platformAdd to GitHub Secrets/GitLab CI vars
Gitleaks blocking commitPre-commit hook found patternVerify it's false positive or fix
Vault connection failsWrong token or expiredCheck VAULT_TOKEN and renewal
Different envs share secretsCopy-paste .env between envsUse separate .env.dev, .env.prod

Related Skills

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/security/secrets-management

Default branch

main

Latest commit

9496306

Tree SHA

fe4e2f1