| name | sast-security-misconfiguration-testing |
| description | Investigate security misconfiguration vulnerabilities including debug modes, default credentials, overly permissive settings, and insecure defaults. Use when threat model identifies CWE-16 (Configuration), CWE-1188 (Insecure Default Initialization), CWE-276 (Incorrect Default Permissions), or configuration concerns. |
| allowed-tools | Read, Grep, Glob |
SAST Security Misconfiguration Testing Skill
Purpose
Investigate security misconfigurations by analyzing:
- Debug/development modes left enabled
- Default credentials and secrets
- Overly permissive settings (CORS, permissions)
- Missing security headers and protections
- Verbose error handling exposing internals
CRITICAL: OWASP A05 Context
Security Misconfiguration is #5 on OWASP Top 10 because:
- Easy to introduce, hard to detect automatically
- Often environment-specific (dev vs prod)
- Can expose entire application
- Frequently exploited in real attacks
Vulnerability Types Covered
1. Debug Mode in Production (CWE-489)
Development/debug settings exposing sensitive information.
Dangerous Patterns:
DEBUG = True
app.run(debug=True)
app.config['DEBUG'] = True
app.config['PROPAGATE_EXCEPTIONS'] = True
if __name__ == '__main__':
app.run(host='0.0.0.0')
app.use(errorHandler({ dumpExceptions: true, showStack: true }))
Safe Patterns:
DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true'
if os.environ.get('ENVIRONMENT') == 'production':
DEBUG = False
assert not app.debug, "Debug must be disabled in production"
2. Default/Hardcoded Credentials (CWE-1188, CWE-798)
Note: CWE-798 overlaps with cryptography-testing but config-specific cases here.
Dangerous Patterns:
DATABASE_URL = "postgresql://admin:admin@localhost/db"
REDIS_URL = "redis://:password123@localhost:6379"
API_KEY = "default_api_key_12345"
SECRET_KEY = "development_secret_key"
DEFAULT_ADMIN_PASSWORD = "admin123"
Safe Patterns:
DATABASE_URL = os.environ['DATABASE_URL']
SECRET_KEY = os.environ['SECRET_KEY']
secret = os.environ.get('SECRET_KEY')
if not secret or secret == 'development_secret_key':
raise ValueError("Production SECRET_KEY required")
3. Overly Permissive CORS (CWE-16)
Cross-Origin Resource Sharing allowing all origins.
Dangerous Patterns:
from flask_cors import CORS
CORS(app)
cors(app, origins='*')
app.use(cors({ origin: '*' }))
cors(app, origins=True, supports_credentials=True)
cors(app, origins=r'.*\.example\.com')
Safe Patterns:
ALLOWED_ORIGINS = [
'https://app.example.com',
'https://admin.example.com'
]
CORS(app, origins=ALLOWED_ORIGINS)
CORS(app, origins=os.environ['ALLOWED_ORIGINS'].split(','))
4. Missing Security Headers (CWE-16)
HTTP headers that prevent common attacks.
Missing Headers to Check:
Safe Patterns:
from flask_talisman import Talisman
Talisman(app, content_security_policy={...})
@app.after_request
def add_security_headers(response):
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['X-Frame-Options'] = 'DENY'
response.headers['Strict-Transport-Security'] = 'max-age=31536000'
return response
const helmet = require('helmet')
app.use(helmet())
5. Insecure Default Permissions (CWE-276)
Files, directories, or resources with overly permissive access.
Dangerous Patterns:
os.chmod(config_file, 0o777)
os.chmod(upload_dir, 0o777)
s3.put_object(Bucket='bucket', Key='file', ACL='public-read')
DATABASES = {
'default': {
'HOST': '0.0.0.0',
}
}
Safe Patterns:
os.chmod(config_file, 0o600)
os.chmod(upload_dir, 0o750)
s3.put_object(Bucket='bucket', Key='file')
DATABASES = {
'default': {
'HOST': '127.0.0.1',
}
}
6. Verbose Error Messages (CWE-209)
Note: Also covered in data-exposure-testing, but config-specific here.
Dangerous Patterns:
@app.errorhandler(Exception)
def handle_error(e):
return str(e), 500
except psycopg2.Error as e:
return f"Database error: {e}", 500
app.use((err, req, res, next) => {
res.status(500).send(err.stack)
})
Safe Patterns:
import logging
logger = logging.getLogger(__name__)
@app.errorhandler(Exception)
def handle_error(e):
logger.exception("Internal error")
return "An error occurred", 500
if app.debug:
return str(e), 500
else:
return "Internal server error", 500
7. Insecure Session Configuration
Session cookies without proper security attributes.
Dangerous Patterns:
app.config['SESSION_COOKIE_SECURE'] = False
app.config['SESSION_COOKIE_HTTPONLY'] = False
app.config['SESSION_COOKIE_SAMESITE'] = None
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=365)
Safe Patterns:
app.config.update(
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='Lax',
PERMANENT_SESSION_LIFETIME=timedelta(hours=1)
)
Investigation Methodology
Step 1: Find Configuration Files
Search for: settings.py, config.py, .env
application.yml, config.json
docker-compose.yml, Dockerfile
nginx.conf, apache.conf
Step 2: Check Debug Settings
Search for: DEBUG, debug=, development
FLASK_ENV, NODE_ENV, RAILS_ENV
app.run(debug
Step 3: Find Credential Patterns
Search for: password, secret, key, token
admin, default, example
localhost, 127.0.0.1
Step 4: Check Security Headers
Search for: helmet, Talisman, SecurityHeaders
Content-Security-Policy, X-Frame-Options
add_header, setHeader
Step 5: Review CORS Configuration
Search for: cors(, CORS(, Access-Control
origin, credentials
allowedOrigins, corsOptions
Step 6: Check Permissions
Search for: chmod, chown, ACL
0777, 0666, public-read
world-readable, world-writable
Classification Criteria
TRUE_POSITIVE:
- DEBUG=True in production configuration
- Hardcoded credentials in non-example files
- CORS allowing all origins with credentials
- Missing critical security headers
- World-writable sensitive files
FALSE_POSITIVE:
- Debug settings in development-only configs
- Example/template credentials clearly marked
- CORS restrictions appropriate for API use case
- Security headers set via reverse proxy (nginx)
- Permissions appropriate for use case
UNVALIDATED:
- Environment-dependent settings need runtime check
- Proxy/infrastructure may add headers
- Context needed to assess permission requirements
Output Format
### Verdict
- **verdict**: TRUE_POSITIVE or FALSE_POSITIVE
- **confidence_score**: 1-10
- **risk_level**: LOW, MEDIUM, HIGH, or CRITICAL
### Misconfiguration Type
- **Category**: Debug Mode / Credentials / CORS / Headers / Permissions
- **Environment**: Production / Development / Unknown
### Evidence
- **Location**: file:line
- **Setting**: [The misconfiguration]
- **Current Value**: [What it's set to]
- **Expected Value**: [What it should be]
### Impact
- [What can an attacker do with this misconfiguration]
### Recommendations
- [Specific fix with code example]
CWE Mapping
Configuration
- CWE-16: Configuration
- CWE-1188: Insecure Default Initialization of Resource
- CWE-276: Incorrect Default Permissions
- CWE-489: Active Debug Code
Related
- CWE-209: Error Message Information Leak
- CWE-215: Insertion of Sensitive Information Into Debugging Code
- CWE-668: Exposure of Resource to Wrong Sphere
Cross-Skill Dependencies
Configuration investigations may need:
- sast-cryptography-testing: For hardcoded secrets
- sast-browser-security-testing: For CORS/cookie settings
- sast-data-exposure-testing: For verbose error handling
Environment-Specific Checks
Docker
# Dangerous
ENV DEBUG=true
ENV SECRET_KEY=development
# Check for
EXPOSE (unnecessary ports)
USER root (running as root)
Kubernetes
securityContext: (missing or permissive)
hostNetwork: true
privileged: true
Cloud (AWS/GCP/Azure)
# Check for
Public S3 buckets
Open security groups
IAM with admin access
Safety Rules
- Only analyze code in the repository provided
- Consider environment context (dev vs prod)
- Check for environment variable overrides
- Look for infrastructure-level compensating controls