| name | secret-hygiene |
| description | This skill activates when detecting hardcoded strings that look like API keys or credentials, creating .env files, referencing process.env or os.environ without Infisical, or working with configuration files that contain sensitive values. It enforces secret hygiene practices and recommends moving secrets to Infisical. |
Secret Hygiene
Patterns for detecting, preventing, and remediating hardcoded secrets in codebases.
Detection Patterns
Common Secret Patterns
Watch for these patterns in code:
# AWS
AKIA[0-9A-Z]{16} # AWS Access Key ID
[0-9a-zA-Z/+]{40} # AWS Secret Access Key
# API Keys
sk_live_[0-9a-zA-Z]{24,} # Stripe secret key
sk_test_[0-9a-zA-Z]{24,} # Stripe test key
SG\.[0-9A-Za-z\-_]{22}\.[0-9A-Za-z\-_]{43} # SendGrid
xoxb-[0-9]{11}-[0-9]{11}-[0-9a-zA-Z]{24} # Slack bot token
# Tokens
ghp_[0-9a-zA-Z]{36} # GitHub personal access token
glpat-[0-9a-zA-Z\-_]{20} # GitLab personal access token
eyJ[A-Za-z0-9-_]+\.eyJ[A-Za-z0-9-_]+ # JWT token
# Database
postgres://.*:.*@ # PostgreSQL connection string
mysql://.*:.*@ # MySQL connection string
mongodb(\+srv)?://.*:.*@ # MongoDB connection string
redis://.*:.*@ # Redis connection string
# Private Keys
-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----
-----BEGIN PGP PRIVATE KEY BLOCK-----
When to Flag
Flag code that contains:
- String literals matching secret patterns above
- Hardcoded connection strings with credentials
- Base64-encoded values assigned to
secret, key, token, or password variables
- Configuration files with inline credentials
Remediation
Step 1: Move Secret to Infisical
infisical secrets set STRIPE_SECRET_KEY=sk_live_abc123 --env=dev
infisical secrets set STRIPE_SECRET_KEY=sk_live_xyz789 --env=production
Step 2: Replace Hardcoded Value
Python (Django):
STRIPE_KEY = "sk_live_abc123"
import os
STRIPE_KEY = os.environ["STRIPE_SECRET_KEY"]
TypeScript (NestJS/Next.js/Hono):
const stripeKey = "sk_live_abc123"
const stripeKey = process.env.STRIPE_SECRET_KEY!
Flutter (Dart):
// Before
const apiKey = "sk_live_abc123";
// After
final apiKey = const String.fromEnvironment('STRIPE_SECRET_KEY');
Step 3: Run with Infisical
infisical run --env=dev -- npm run dev
infisical run --env=production -- node server.js
.env Hygiene
.gitignore Requirements
Every project must have these in .gitignore:
# Environment files with secrets
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
.env.*.local
# Keep example committed
!.env.example
.env.example Maintenance
Maintain .env.example with every secret key (no values):
infisical secrets generate-example-env --env=dev > .env.example
Format with comments:
NODE_ENV=
PORT=
APP_URL=
DATABASE_URL=
DB_POOL_SIZE=
JWT_SECRET=
SESSION_SECRET=
STRIPE_SECRET_KEY=
SENDGRID_API_KEY=
Git Hygiene
Pre-Commit Scanning
Install the Infisical pre-commit hook:
infisical scan install --pre-commit-hook
Or use .pre-commit-config.yaml:
repos:
- repo: local
hooks:
- id: infisical-scan
name: Infisical Secret Scan
entry: infisical scan git-changes --staged
language: system
pass_filenames: false
If a Secret Was Committed
- Rotate immediately - the secret is compromised
- Remove from code and replace with env var reference
- Update in Infisical with the new rotated value
- Do NOT just delete the commit - the secret exists in git history
infisical secrets set COMPROMISED_KEY=new_rotated_value --env=production
Framework-Specific Patterns
Django
import os
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
DEBUG = os.environ.get("DEBUG", "False").lower() == "true"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ["DB_NAME"],
"USER": os.environ["DB_USER"],
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": os.environ["DB_HOST"],
"PORT": os.environ.get("DB_PORT", "5432"),
}
}
Run: infisical run --env=dev -- python manage.py runserver
Next.js
const config = {
env: {
}
}
Run: infisical run --env=dev -- npm run dev
NestJS
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
],
})
export class AppModule {}
Run: infisical run --env=dev -- npm run start:dev
Hono (Cloudflare Workers)
Run: infisical run --env=dev -- wrangler dev
Anti-Patterns
Hardcoded Secrets in Code
API_KEY = "sk_live_abc123"
DB_PASSWORD = "supersecret"
Same Secrets Across Environments
Each environment (dev, staging, production) must have unique credentials. Sharing production secrets with development is a security risk.
Secrets as CLI Arguments
node server.js --db-password=secret123
infisical run --env=production -- node server.js
Secrets in Docker Image Layers
# NEVER - persists in image history
ENV API_KEY=sk_live_abc123
RUN echo "password=secret" > /app/.env
# CORRECT - inject at runtime
CMD ["infisical", "run", "--env=production", "--", "node", "server.js"]
Secrets in Log Output
console.log(`Connecting with key: ${process.env.API_KEY}`)
console.log("Connecting to API service...")
Committing .env Files
git ls-files --error-unmatch .env 2>/dev/null && echo "WARNING: .env is tracked!"
If .env is already tracked:
git rm --cached .env
echo ".env" >> .gitignore
git commit -m "fix: remove .env from tracking"