/scan-secrets Command
Scan codebase for exposed secrets and unencrypted sensitive data
Scan the codebase for exposed secrets that should not be committed to Git.
This is a GitOps repository where ALL secrets must be SOPS-encrypted.
Scan Categories
1. Unencrypted SOPS Files
Check all *.sops.yaml and *.sops.yml files to verify they are properly encrypted:
# Find all SOPS files
find . -name "*.sops.yaml" -o -name "*.sops.yml" | grep -v node_modules
# For each file, check if it contains the SOPS metadata block
# Encrypted files MUST have: sops.age or sops.encrypted_regex sections
Red flags:
*.sops.*files withoutsops:metadata block at the bottomstringData:ordata:values that are NOTENC[AES256_GCM,...]
2. High-Entropy Strings (Potential Secrets)
Search for patterns that indicate exposed secrets:
# API keys and tokens
rg -i "(api[_-]?key|api[_-]?token|auth[_-]?token|bearer|secret[_-]?key)" --type yaml --type json
# Base64 encoded secrets (longer than 20 chars, not in SOPS files)
rg "[A-Za-z0-9+/]{40,}={0,2}" --type yaml | grep -v "\.sops\." | grep -v "ENC\["
# AWS/Cloud credentials
rg -i "(aws[_-]?access|aws[_-]?secret|AKIA[A-Z0-9]{16})"
# Private keys
rg "PRIVATE KEY" --type yaml --type json
rg "BEGIN RSA"
rg "BEGIN EC"
rg "BEGIN OPENSSH"
3. Known Secret File Patterns
Check for files that should NEVER be committed:
# Files that should be in .gitignore
find . -name "*.pem" -o -name "*.key" -o -name "id_rsa*" -o -name "*.p12" -o -name "*.pfx" 2>/dev/null | grep -v ".gitignore"
# Environment files with secrets
find . -name ".env" -o -name ".env.*" -o -name "*.env" 2>/dev/null | head -20
# Credential files
find . -name "credentials*" -o -name "*password*" -o -name "*secret*" 2>/dev/null | grep -v ".sops." | grep -v ".md"
4. Kubernetes Secret Manifests
All Kubernetes Secrets MUST be SOPS-encrypted:
# Find Secret manifests that are NOT sops files
rg "kind: Secret" --type yaml -l | grep -v "\.sops\."
5. Hardcoded Passwords in HelmReleases
Check for inline passwords in HelmRelease values:
rg -i "(password|passwd|pwd):" kubernetes/ --type yaml | grep -v "passwordSecretRef" | grep -v "existingSecret"
6. Cloudflare/External Service Tokens
Check for exposed service credentials:
rg -i "(cloudflare|tunnel|CF_)" --type yaml | grep -v "secretKeyRef" | grep -v "\.sops\."
rg "tunnel:" kubernetes/ --type yaml -A5 | grep -i "secret\|token\|credential"
Output Format
For each finding, report:
| Severity | File | Line | Issue | Recommendation | |----------|------|------|-------|----------------| | 🔴 Critical | path/to/file | 42 | Unencrypted API key | Encrypt with SOPS | | 🟡 Warning | path/to/file | 15 | Hardcoded password | Use secretKeyRef | | 🟢 Info | path/to/file | 8 | High-entropy string | Verify if sensitive |
Severity Levels
- 🔴 Critical: Confirmed exposed secret (API keys, passwords, tokens in plaintext)
- 🟡 Warning: Potential secret or misconfiguration (hardcoded values that should use refs)
- 🟢 Info: Suspicious pattern that needs manual review
Expected Safe Patterns
These patterns are SAFE and should NOT be flagged:
# Safe: References to secrets (not the secrets themselves)
secretKeyRef:
name: my-secret
key: password
# Safe: SOPS-encrypted values
password: ENC[AES256_GCM,data:xyz123,...]
# Safe: Flux variable substitution
token: ${SECRET_CLOUDFLARE_TOKEN}
# Safe: Helm value references
password: "{{ .Values.auth.password }}"
Remediation Guide
If secrets are found:
- Immediately: Do NOT commit. If already committed, consider the secret compromised.
- Rotate: Generate new credentials for any exposed secrets.
- Encrypt: Move secret to a
*.sops.yamlfile and encrypt:sops --encrypt --in-place path/to/secret.sops.yaml - Reference: Update manifests to use
secretKeyRefor Flux substitution. - Verify: Run
task configureto validate encryption.
After Scanning
Provide:
- Summary: Total files scanned, issues found by severity
- Findings table: Detailed list of all issues
- Recommendations: Prioritized remediation steps
- Verification command: How to re-scan after fixes