From harness-claude
Scans source code, configs, .env files, and git history for hardcoded secrets, API keys, credentials. Audits .gitignore coverage, classifies risks by severity, recommends vault externalization.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Secret detection, credential hygiene, and vault integration. Find exposed secrets, classify risk, and enforce externalization before they reach production.
Scans codebases for hardcoded secrets, API keys (Stripe, Supabase, AWS, GitHub, Slack), bearer tokens, passwords, private keys, and base64 secrets using grep regex patterns on JS/TS/JSON/YAML files.
Scans code, git history, and configs for secrets like API keys, cloud credentials, private keys, and DB strings using regex, entropy, and context. Assesses severity and generates remediation reports.
Detects hardcoded secrets like API keys, tokens, and credentials in git repos using Gitleaks regex and entropy analysis. Guides repo scans, pre-commit hooks, CI/CD integration, audits.
Share bugs, ideas, or general feedback.
Secret detection, credential hygiene, and vault integration. Find exposed secrets, classify risk, and enforce externalization before they reach production.
.env file managementScan source files for secret patterns. Search for common secret formats:
sk-, pk_, AKIA, AIza, ghp_, glpat-, xoxb-postgres://user:pass@)-----BEGIN RSA PRIVATE KEY-----, -----BEGIN EC PRIVATE KEY-----eyJ header patternpassword, secret, token, api_key with literal string valuesScan configuration files. Check files that commonly contain secrets:
.env, .env.local, .env.production (should be gitignored)config/*.json, config/*.yaml with credential fieldsdocker-compose.yml with inline environment valuesapplication.properties, appsettings.json with connection stringsCheck .gitignore coverage. Verify that sensitive files are excluded from version control:
.env* files (except .env.example)*.pem, *.key private key filescredentials/, secrets/ directories*-credentials.json)Scan git history for leaked secrets. Check recent commits:
git log --diff-filter=A --name-only for recently added files.env or credential files were committed and later removedPresent scan results:
Secret Scan: 7 findings in 5 files
CRITICAL (2):
src/config/database.ts:8 -- Hardcoded PostgreSQL connection string with password
src/services/stripe.ts:3 -- Stripe secret key (sk_example_...)
HIGH (3):
docker-compose.yml:15 -- MySQL root password in plaintext
src/config/aws.ts:12 -- AWS access key pattern (AKIA...)
.env.production:1 -- File committed to git (should be gitignored)
MEDIUM (2):
src/utils/auth.ts:45 -- JWT secret as string literal
config/app.json:22 -- Generic "apiKey" field with literal value
Assign severity levels. Classify each finding:
YOUR_API_KEY_HERE), test-only credentials in test fixtures.Identify secret type. Categorize each finding:
Assess blast radius. For each CRITICAL and HIGH finding:
Check for false positives. Verify findings are actual secrets:
Generate classification report:
Classification:
CRITICAL: 2 (require immediate rotation)
HIGH: 3 (require rotation within 24 hours)
MEDIUM: 2 (require externalization)
LOW: 0
False positives: 1 (removed from findings)
Affected systems:
- PostgreSQL database (production)
- Stripe payment processing
- AWS S3 storage
Recommend secret externalization. For each finding, provide the remediation:
.env.example with a placeholder value.gitignore includes the actual .env fileRecommend secret management integration. Based on the project's infrastructure:
Recommend rotation procedure. For each CRITICAL and HIGH finding:
Provide code transformation examples. Show before/after for each finding:
// BEFORE (hardcoded)
const stripe = new Stripe('sk_example_abc123...');
// AFTER (externalized)
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
If --fix flag is set, apply automatic transformations:
.env.example entries with placeholder values.gitignore if .env files are not excludedRe-scan after remediation. Run the same scan from Phase 1 to verify:
Verify .gitignore coverage. Confirm:
.env files (except .env.example) are gitignoredVerify .env.example completeness. Check that:
Check git history for residual exposure. If secrets were previously committed:
git filter-repo or BFG Repo-Cleaner for history rewritingGenerate validation report:
Secret Validation: [PASS/WARN/FAIL]
Rescan: PASS (0 CRITICAL, 0 HIGH findings)
.gitignore: PASS (all sensitive patterns covered)
.env.example: WARN (missing STRIPE_WEBHOOK_SECRET entry)
Git history: WARN (2 secrets exist in history -- rotation required)
Actions remaining:
1. Add STRIPE_WEBHOOK_SECRET to .env.example
2. Rotate PostgreSQL password (exposed in commit abc1234)
3. Rotate Stripe key (exposed in commit def5678)
4. Consider git history rewrite after rotation
harness skill run harness-secrets -- Primary invocation for secret scanning and remediation.harness validate -- Run after remediation to verify project health.harness check-security -- Complementary mechanical security scan that includes basic secret detection.emit_interaction -- Present findings and gather decisions on remediation approach..gitignore covers all sensitive file patterns.env.example is complete with placeholder valuesPhase 1: SCAN
Scanned: 86 files
Findings: 4
CRITICAL: src/payments/stripe.ts:5 -- sk_example_EXAMPLE_KEY_REDACTED_0000
HIGH: docker-compose.yml:22 -- POSTGRES_PASSWORD=supersecret
MEDIUM: src/config/jwt.ts:3 -- JWT_SECRET = "my-jwt-secret-key"
LOW: tests/fixtures/auth.ts:8 -- fake-api-key-for-testing (false positive)
Phase 2: CLASSIFY
CRITICAL: 1 (Stripe production secret key -- full payment access)
HIGH: 1 (PostgreSQL password -- database access)
MEDIUM: 1 (JWT secret -- token forgery risk)
False positives: 1 (test fixture removed from findings)
Phase 3: REMEDIATE
1. Stripe key -> process.env.STRIPE_SECRET_KEY
2. Postgres password -> ${POSTGRES_PASSWORD} in compose, actual value in .env
3. JWT secret -> process.env.JWT_SECRET
Added 3 entries to .env.example
Updated .gitignore with .env* pattern
Phase 4: VALIDATE
Rescan: PASS (0 findings)
.gitignore: PASS
.env.example: PASS (all 3 variables documented)
Git history: WARN (Stripe key in commit history)
Result: WARN -- secrets externalized, rotation required for Stripe and Postgres
Phase 1: SCAN
Scanned: 124 files
Findings: 5
CRITICAL: settings/production.py:45 -- AWS_ACCESS_KEY_ID = "AKIA..."
CRITICAL: settings/production.py:46 -- AWS_SECRET_ACCESS_KEY = "wJal..."
HIGH: .env.production committed to git (12 secrets inside)
MEDIUM: settings/base.py:88 -- SECRET_KEY = "django-insecure-..."
MEDIUM: settings/base.py:92 -- DATABASE_URL with embedded password
Phase 2: CLASSIFY
CRITICAL: 2 (AWS IAM credentials -- full account access)
HIGH: 1 (.env.production in git -- 12 leaked values)
MEDIUM: 2 (Django secret key and database URL)
Phase 3: REMEDIATE
1. AWS credentials -> boto3 credential chain (env vars or IAM role)
2. Remove .env.production from git, add to .gitignore
3. Django SECRET_KEY -> os.environ["DJANGO_SECRET_KEY"]
4. DATABASE_URL -> os.environ["DATABASE_URL"]
Recommend: Switch to django-environ for all settings
Recommend: Use IAM roles instead of access keys for production
Phase 4: VALIDATE
Rescan: PASS
.gitignore: PASS
.env.example: PASS
Git history: CRITICAL (AWS keys and .env.production in history)
Result: FAIL -- rotation required before deployment, history rewrite recommended
| Rationalization | Reality |
|---|---|
| "That key is read-only so it's not a big deal if it leaks" | Read-only credentials still enable data exfiltration, reconnaissance, and discovery of other vulnerabilities. A leaked read-only database credential exposes every row in the database. Scope does not eliminate risk. |
| "We removed it from the file — it's cleaned up now" | Removing a secret from the current tree does not remove it from git history. Anyone with a clone of the repository can recover the secret with git log -p. Rotation is required regardless of file deletion. |
| "That's a test environment key, not production" | Test environment credentials are frequently reused, shared informally, and rotated less often. Leaked test keys also reveal credential patterns and naming conventions that help attackers guess production secrets. |
| "It's in a private repo so only our team can see it" | Private repos are accessed by CI/CD systems, third-party integrations, contractors, and former employees. Repository access controls are not a substitute for secret externalization. Breaches routinely originate from compromised internal access. |
| "We'll move it to an environment variable before we deploy" | Intent does not prevent exposure. The secret is in the codebase now and may already be in commit history, CI logs, or developer machine caches. Remediation must happen at the moment of detection, not at deployment time. |
.env files with actual secrets committed to git. A committed .env file containing real credentials is a blocking finding, even if the file is later gitignored.--fix flag must be followed by a rescan to confirm all findings are resolved..harness/secret-scan-ignore file with documented exceptions for known false positives (test fixtures, example values, hash constants).