Agent skill

insecure-defaults

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.

Stars 458
Forks 38

Install this agent skill to your Project

npx add-skill https://github.com/vibeeval/vibecosystem/tree/main/skills/insecure-defaults

SKILL.md

Insecure Defaults Detection

Systematic detection of security misconfigurations where the default behavior is insecure. These are the bugs that ship because "it worked in development."

Detection Categories

1. Fail-Open Configurations

Code that defaults to allowing access when a security check fails.

typescript
// 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.

2. Hardcoded Secrets

typescript
// 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:

  • String literals assigned to variables named *key*, *secret*, *password*, *token*, *credential*
  • Base64-encoded strings in source (potential embedded keys)
  • Bearer followed by a string literal
  • AWS access keys (AKIA...), GitHub tokens (ghp_...), Stripe keys (sk_live_...)

3. Weak Authentication Defaults

typescript
// 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
}))

4. Permissive CORS

typescript
// 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']
}))

5. Disabled Security Features

typescript
// 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.

6. Debug Mode in Production

typescript
// 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)
}

7. Overly Permissive File/Directory Permissions

bash
# BAD
chmod 777 /app/config
chmod 666 /app/.env

# GOOD
chmod 600 /app/.env
chmod 700 /app/config

8. Missing Rate Limiting

typescript
// 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)

9. Insecure Deserialization

typescript
// 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 })

10. Missing Security Headers

Required headers for web applications:

typescript
// 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()
})

Audit Checklist

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

Rationalizations to Reject

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

Integration with vibecosystem

  • security-reviewer agent: Primary consumer -- runs this checklist on every review
  • code-reviewer agent: Flags obvious insecure defaults during general review
  • config-validator agent: Applies these patterns to configuration files
  • verifier agent: Includes insecure default check in final quality gate

Inspired by Trail of Bits insecure-defaults plugin.

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results