Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/trailofbits/skills/llms.txt

Use this file to discover all available pages before exploring further.

Security skill for detecting insecure default configurations that create vulnerabilities when applications run with missing or incomplete configuration. Focuses on fail-open patterns where apps run insecurely rather than crash safely.

Overview

The insecure-defaults plugin identifies security vulnerabilities caused by dangerous default values that allow applications to run in production with weak or missing security controls. It distinguishes between fail-secure patterns (app crashes) and fail-open patterns (app runs insecurely).
Author: Trail of Bits
Version: 1.0.0
Critical Distinction: Applications that crash without proper configuration are safe (fail-secure). Applications that run with insecure defaults are vulnerable (fail-open).

Vulnerability Categories

The plugin detects five categories of insecure defaults:

Hardcoded Fallback Secrets

JWT keys, API keys, session secrets with fallback values

Default Credentials

admin/admin, root/password, test API keys

Weak Cryptographic Defaults

MD5, DES, ECB mode for security-sensitive operations

Permissive Access Control

CORS *, public by default, world-writable permissions

Missing Security Configuration

Authentication disabled by default, debug mode enabled

When to Use

Use this skill when:
  • Security auditing production applications or services
  • Configuration review of deployment manifests (Docker, Kubernetes, IaC)
  • Pre-production checks before deploying new services
  • Code review of authentication, authorization, or cryptographic code
  • Environment variable handling analysis for secrets management
  • API security review checking CORS, rate limiting, authentication
  • Third-party integration review for hardcoded test credentials

When NOT to Use

Do not use this skill for:
  • Test fixtures explicitly scoped to test environments (test/, spec/, __tests__/)
  • Example/template files (.example, .template, .sample suffixes)
  • Development-only tools (local Docker Compose for dev, debug scripts)
  • Documentation examples in README.md or docs/ directories
  • Build-time configuration that gets replaced during deployment
  • Crash-on-missing behavior where app won’t start without proper config (fail-secure)
When in doubt: trace the code path to determine if the app runs with the default or crashes.

Installation

/plugin install insecure-defaults

Workflow

Follow this workflow for every potential finding:
1

SEARCH: Project Discovery

Determine language, framework, and project conventions. Find secret storage locations, credentialed integrations, cryptography usage, and security configuration.
2

VERIFY: Actual Behavior

Trace code paths to understand runtime behavior. Determine what happens if configuration is missing.
3

CONFIRM: Production Impact

Check if production config provides the variable or if the insecure default reaches production.
4

REPORT: With Evidence

Document location, pattern, verification results, production impact, and exploitation scenario.

Category 1: Fallback Secrets

Vulnerable Patterns

# File: src/auth/jwt.py
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-secret-key-123')

# Used in security context
def create_token(user_id):
    return jwt.encode({'user_id': user_id}, SECRET_KEY, algorithm='HS256')
Why vulnerable: App runs with known secret if env var is missing. Attacker can forge tokens/access database.

Secure Patterns

# File: src/auth/jwt.py
SECRET_KEY = os.environ['SECRET_KEY']  # Raises KeyError if missing

# App won't start without SECRET_KEY - fail-secure

Category 2: Default Credentials

Vulnerable Patterns

# File: src/models/user.py
def bootstrap_admin():
    """Create default admin account if none exists"""
    if not User.query.filter_by(role='admin').first():
        admin = User(
            username='admin',
            password=hash_password('admin123'),
            role='admin'
        )
        db.session.add(admin)
        db.session.commit()
Why vulnerable: Default admin accounts or test credentials reach production if env vars missing.

Secure Patterns

Disabled default account
# File: src/models/user.py
def bootstrap_admin():
    """Admin account MUST be configured via environment"""
    username = os.environ['ADMIN_USERNAME']
    password = os.environ['ADMIN_PASSWORD']

    if not User.query.filter_by(username=username).first():
        admin = User(username=username, password=hash_password(password), role='admin')
        db.session.add(admin)

Category 3: Fail-Open Security

Vulnerable Patterns

# File: config/security.py
REQUIRE_AUTH = os.getenv('REQUIRE_AUTH', 'false').lower() == 'true'

@app.before_request
def check_auth():
    if not REQUIRE_AUTH:
        return  # Skip auth check
    # ... auth logic
Why vulnerable: Default is insecure. App runs without authentication, accepts requests from any origin, or leaks stack traces if env var missing.

Secure Patterns

# File: config/security.py
REQUIRE_AUTH = os.getenv('REQUIRE_AUTH', 'true').lower() == 'true'  # Default: true

# Or better - crash if not explicitly configured
REQUIRE_AUTH = os.environ['REQUIRE_AUTH'].lower() == 'true'

Category 4: Weak Crypto

Vulnerable Patterns

# File: src/auth/passwords.py
import hashlib

def hash_password(password):
    """Hash user password"""
    return hashlib.md5(password.encode()).hexdigest()
Why vulnerable:
  • MD5 is cryptographically broken, rainbow tables exist
  • DES has 56-bit keys (brute-forceable), ECB mode leaks patterns
  • SHA1 collisions exist
Use bcrypt/Argon2 for passwords, AES-GCM for encryption, SHA256+ for signatures.

Secure Patterns

# File: src/auth/passwords.py
import bcrypt

def hash_password(password):
    return bcrypt.hashpw(password.encode(), bcrypt.gensalt())
Weak crypto for non-security checksums (cache keys, ETags) is acceptable.

Category 5: Permissive Access

Vulnerable Patterns

# File: src/storage/files.py
def create_secure_file(path):
    fd = os.open(path, os.O_CREAT | os.O_WRONLY, 0o666)  # rw-rw-rw-
    return fd
Why vulnerable:
  • Any user can write to file (should be 0o600 or 0o644)
  • Sensitive data exposed publicly
  • CORS misconfiguration allows credential theft from any site

Search Patterns

Use these grep patterns to discover insecure defaults:
grep -r "getenv.*\) or ['\"]" **/config/ **/auth/
grep -r "process\.env\.[A-Z_]+ \|\| ['\"]" src/
grep -r "ENV\.fetch.*default:" config/
grep -r "password.*=.*['\"][^'\"]{8,}['\"]" src/
grep -r "api[_-]?key.*=.*['\"][^'\"]+['\"]" config/
grep -r "secret.*=.*['\"][^'\"]+['\"]" --include="*.py" --include="*.js"
grep -r "DEBUG.*=.*true" config/
grep -r "AUTH.*=.*false" src/
grep -r "CORS.*=.*\*" server/
grep -r "MD5\|SHA1\|DES\|RC4\|ECB" src/auth/ src/crypto/

Rationalizations to Reject

Reject these shortcuts that lead to missed findings:
RationalizationWhy It’s Wrong
”It’s just a development default”If it reaches production code, it’s a finding
”The production config overrides it”Verify prod config exists; code-level vulnerability remains
”This would never run without proper config”Prove it with code trace; many apps fail silently
”It’s behind authentication”Defense in depth; compromised session still exploits weak defaults
”We’ll fix it before release”Document now; “later” rarely comes

Report Format

For each finding, document:
Finding: Hardcoded JWT Secret Fallback
Location: src/auth/jwt.ts:15
Pattern: const secret = process.env.JWT_SECRET || 'default';

Verification: App starts without JWT_SECRET; secret used in jwt.sign() at line 42
Production Impact: Dockerfile missing JWT_SECRET
Exploitation: Attacker forges JWTs using 'default', gains unauthorized access

Severity: CRITICAL

Build docs developers (and LLMs) love