skills/insecure-defaults/SKILL.md
Detect fail-open configurations, hardcoded secrets, weak authentication defaults, permissive CORS, disabled security features, and other insecure-by-default patterns. Adapted from Trail of Bits. Use during security review or when auditing configuration and initialization code.
npx skillsauth add rubicanjr/FinCognis insecure-defaultsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Systematic detection of security misconfigurations where the default behavior is insecure. These are the bugs that ship because "it worked in development."
Code that defaults to allowing access when a security check fails.
// BAD: Fail-open -- if auth service is down, everyone gets in
async function checkAuth(token: string): Promise<boolean> {
try {
return await authService.verify(token)
} catch {
return true // INSECURE: fails open
}
}
// GOOD: Fail-closed -- if auth service is down, deny access
async function checkAuth(token: string): Promise<boolean> {
try {
return await authService.verify(token)
} catch {
return false // SECURE: fails closed
}
}
Detection pattern: Look for catch blocks that return truthy/permissive values in auth/authz code.
// BAD patterns -- detect ALL of these
const API_KEY = "sk-proj-abc123"
const DB_PASSWORD = "admin123"
const JWT_SECRET = "super-secret-key"
const ENCRYPTION_KEY = Buffer.from("0123456789abcdef")
// GOOD
const API_KEY = process.env.API_KEY
if (!API_KEY) throw new Error('API_KEY environment variable required')
Detection patterns:
*key*, *secret*, *password*, *token*, *credential*Bearer followed by a string literalAKIA...), GitHub tokens (ghp_...), Stripe keys (sk_live_...)// BAD: Session without secure flags
app.use(session({
secret: 'keyboard cat', // Hardcoded secret
cookie: {} // Missing secure, httpOnly, sameSite
}))
// GOOD
app.use(session({
secret: process.env.SESSION_SECRET,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // No JS access
sameSite: 'strict', // CSRF protection
maxAge: 3600000 // 1 hour expiry
},
resave: false,
saveUninitialized: false
}))
// BAD: Allow everything
app.use(cors()) // Defaults to origin: '*'
app.use(cors({ origin: '*' })) // Explicit wildcard
app.use(cors({ origin: true })) // Reflect any origin
// GOOD: Explicit allowlist
app.use(cors({
origin: ['https://app.example.com', 'https://admin.example.com'],
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}))
// BAD: Disabling security in code (not just config)
app.disable('x-powered-by') // This one is actually GOOD
// But these are BAD:
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' // Disable TLS verification
helmet({ contentSecurityPolicy: false }) // Disable CSP
app.use(csrf({ ignoreMethods: ['POST'] })) // Disable CSRF for POST
Detection pattern: Look for false, '0', disable, skip, ignore near security-related configs.
// BAD: Debug flags that leak info
app.use(errorHandler({ dumpExceptions: true, showStack: true }))
mongoose.set('debug', true)
app.set('env', 'development') // Hardcoded to dev
// GOOD: Environment-aware
if (process.env.NODE_ENV !== 'production') {
mongoose.set('debug', true)
}
# BAD
chmod 777 /app/config
chmod 666 /app/.env
# GOOD
chmod 600 /app/.env
chmod 700 /app/config
// BAD: No rate limit on auth endpoints
app.post('/api/login', loginHandler)
app.post('/api/register', registerHandler)
app.post('/api/forgot-password', forgotPasswordHandler)
// GOOD: Rate limited
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 attempts
message: 'Too many attempts, try again later'
})
app.post('/api/login', authLimiter, loginHandler)
// BAD: Deserializing untrusted input
const data = JSON.parse(userInput) // JSON is generally safe
const obj = yaml.load(userInput) // YAML can execute code!
const result = eval(userInput) // Never ever
// GOOD
const obj = yaml.load(userInput, { schema: yaml.FAILSAFE_SCHEMA })
Required headers for web applications:
// Minimum security headers
app.use(helmet()) // Sets many headers, but verify:
// Or manually:
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff')
res.setHeader('X-Frame-Options', 'DENY')
res.setHeader('X-XSS-Protection', '0') // Disabled intentionally, CSP replaces it
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')
res.setHeader('Content-Security-Policy', "default-src 'self'")
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin')
res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()')
next()
})
Authentication:
[ ] No hardcoded secrets in source code
[ ] Session cookies have secure, httpOnly, sameSite flags
[ ] JWT secrets are env vars, not constants
[ ] Password hashing uses bcrypt/argon2 (not MD5/SHA1)
[ ] Default admin passwords don't exist
Authorization:
[ ] Fail-closed on error (deny by default)
[ ] No wildcard permissions in defaults
[ ] Role checks can't be bypassed by omitting headers
Network:
[ ] CORS is not wildcard in production
[ ] TLS verification is not disabled
[ ] Rate limiting on auth and sensitive endpoints
[ ] Security headers are set
Configuration:
[ ] Debug mode is off in production
[ ] Stack traces are not exposed to users
[ ] Error messages don't leak internals
[ ] File permissions are restrictive (600/700)
Data:
[ ] No sensitive data in logs
[ ] No PII in URLs/query strings
[ ] Encryption keys are not hardcoded
[ ] Database connections use TLS
| Rationalization | Why It's Wrong | Required Action | |----------------|---------------|-----------------| | "It's just for development" | Dev configs ship to prod constantly | Use env-based config switching | | "We'll secure it before launch" | Deadline pressure skips security | Secure by default NOW | | "The firewall protects us" | Firewalls have holes, cloud is complex | Defense in depth required | | "It's an internal API" | Internal = one hop from external | Treat as semi-trusted | | "Nobody knows this endpoint exists" | Security through obscurity fails | Authenticate everything |
Inspired by Trail of Bits insecure-defaults plugin.
development
Goal-based workflow orchestration - routes tasks to specialist agents based on user goals
tools
Wiring Verification
development
Connection management, room patterns, reconnection strategies, message buffering, and binary protocol design.
development
Screenshot comparison QA for frontend development. Takes a screenshot of the current implementation, scores it across multiple visual dimensions, and returns a structured PASS/REVISE/FAIL verdict with concrete fixes. Use when implementing UI from a design reference or verifying visual correctness.