| name | Logging Failures |
| description | This skill should be used when the user asks about "logging failures", "log injection", "insufficient logging", "audit logging", "security logging", "CWE-117", or needs to find logging-related vulnerabilities during whitebox security review. |
| version | 1.0.0 |
Logging & Alerting Failures (OWASP A09)
Purpose
Provide detection patterns for logging vulnerabilities including log injection, insufficient logging of security events, secrets in logs, and log tampering vulnerabilities.
OWASP Top 10 Mapping
Category: A09 - Security Logging & Alerting Failures
CWEs:
- CWE-117: Improper Output Neutralization for Logs
- CWE-223: Omission of Security-Relevant Information
- CWE-532: Insertion of Sensitive Information into Log File
- CWE-778: Insufficient Logging
When to Use
Activate this skill when:
- Reviewing logging implementations
- Checking for log injection vulnerabilities
- Auditing security event logging
- Looking for secrets exposed in logs
- Verifying audit trail completeness
Log Injection (CWE-117)
Overview
Log injection occurs when user-controlled input is written to logs without sanitization, allowing attackers to inject fake log entries or manipulate log output.
Detection Patterns
Python
grep -rniE "logging\.(info|debug|error|warn).*\+|logger\.(info|debug|error|warn).*\+" --include="*.py"
grep -rniE "logging\.(info|debug|error|warn).*f['\"]|logger\..*\.format\(" --include="*.py"
Vulnerable:
logger.info(f"User login: {request.form['username']}")
Secure:
logger.info("User login", extra={"username": sanitize(username)})
Java
grep -rniE "log\.(info|debug|error|warn).*\+|logger\.(info|debug|error|warn).*\+" --include="*.java"
grep -rniE "String\.format.*log|log.*String\.format" --include="*.java"
Vulnerable:
logger.info("User login: " + username);
Secure:
logger.info("User login: {}", sanitize(username));
Go
grep -rniE "log\.Printf|log\.Print.*\+" --include="*.go"
grep -rniE "zap\.String.*request|logrus\.WithField.*request" --include="*.go"
Vulnerable:
log.Printf("User login: %s", userInput)
Secure:
logger.Info("user login", zap.String("username", sanitize(username)))
TypeScript
grep -rniE "console\.(log|info|error|warn).*\+|logger\.(log|info|error|warn).*\+" --include="*.ts"
PHP
grep -rniE "error_log.*\$_|syslog.*\$_|log.*\$_(GET|POST|REQUEST)" --include="*.php"
Log Injection Payloads
# Inject fake log entry
username: legitimate_user\n[ERROR] Admin password changed by attacker
# Inject multiple lines
input: line1\n[INFO] Fake entry\n[DEBUG] More fake entries
# ANSI escape codes (terminal injection)
input: \x1b[2J\x1b[1;1H # Clear terminal
Insufficient Logging (CWE-778)
Overview
Missing logs for security-critical events prevents detection of attacks and incident response.
Events That MUST Be Logged
| Event Category | Specific Events |
|---|
| Authentication | Login success/failure, logout, password change |
| Authorization | Access denied, privilege escalation attempts |
| Input Validation | Rejected/suspicious input |
| Session | Session creation, destruction, timeout |
| Data Access | Sensitive data read/write/delete |
| Configuration | Settings changes, feature toggles |
| Errors | Exceptions, failures (without stack traces) |
Detection Patterns
grep -rniE "def (login|authenticate|authorize|check_permission)" --include="*.py" -A 10 | grep -v "log\."
grep -rniE "except.*:|catch\s*\(" --include="*.py" --include="*.java" -A 5 | grep -v "log\|logger"
grep -rniE "has_permission|is_admin|check_role" --include="*.go" --include="*.py" --include="*.java" -A 5 | grep -v "log"
What to Check
grep -rniE "login|authenticate|logout" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php" | xargs -I {} sh -c 'grep -l "log" {} || echo "MISSING: {}"'
grep -rniE "forbidden|unauthorized|access.*denied" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
grep -rniE "delete|update|insert" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php" | xargs -I {} sh -c 'grep -l "log\|audit" {} || echo "MISSING: {}"'
Secrets in Logs (CWE-532)
Overview
Logging sensitive data (passwords, tokens, API keys) exposes them to anyone with log access.
Detection Patterns
grep -rniE "log.*(password|passwd|pwd|secret|token|api_key|apikey|credential)" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
grep -rniE "log.*request\.body|log.*req\.body|log.*getBody" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
grep -rniE "log.*user\)|log.*%v.*user|log.*JSON\.stringify" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
Sensitive Fields to Never Log
password, passwd, pwd
token, access_token, refresh_token
api_key, apikey, secret_key
credit_card, ccn, cvv
ssn, social_security
private_key, secret
- Authorization headers
- Session IDs
Secure Pattern - Field Redaction
SENSITIVE_FIELDS = ['password', 'token', 'api_key', 'secret']
def redact_sensitive(data: dict) -> dict:
return {k: '***REDACTED***' if k.lower() in SENSITIVE_FIELDS else v
for k, v in data.items()}
logger.info("User data", extra=redact_sensitive(user_data))
func redactSensitive(data map[string]interface{}) map[string]interface{} {
sensitive := []string{"password", "token", "api_key"}
for _, key := range sensitive {
if _, exists := data[key]; exists {
data[key] = "***REDACTED***"
}
}
return data
}
Log Tampering
Overview
If logs can be modified or deleted, attackers can cover their tracks.
Detection Patterns
grep -rniE "logfile\s*=|LOG_FILE\s*=|log_path\s*=" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php" --include="*.env"
grep -rniE "log.*request\.(path|param|query)" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
grep -rniE "RotatingFileHandler|logrotate|rotate.*log" --include="*.go" --include="*.py" --include="*.java" --include="*.conf"
Secure Patterns
- Write logs to append-only storage
- Use centralized logging (SIEM)
- Implement log integrity verification (signing)
- Restrict log file permissions
- Use remote logging to prevent local tampering
Missing Alerting
Overview
Logs without alerts allow attacks to go unnoticed.
Events That Should Alert
| Event | Alert Priority |
|---|
| Multiple failed logins | HIGH |
| Admin actions | MEDIUM |
| Privilege escalation | CRITICAL |
| Sensitive data access | HIGH |
| Configuration changes | MEDIUM |
| Error rate spike | HIGH |
| Unusual access patterns | MEDIUM |
Detection Patterns
grep -rniE "alert|notify|pagerduty|slack.*webhook|email.*notify" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.yaml" --include="*.json"
grep -rniE "threshold|rate_limit|max_attempts|lockout" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
Language-Specific Secure Logging
Python (structlog)
import structlog
logger = structlog.get_logger()
logger.info(
"user_login",
username=sanitize(username),
ip_address=request.remote_addr,
success=True
)
Java (SLF4J + Logback)
MDC.put("userId", sanitize(userId));
MDC.put("action", "login");
logger.info("User authentication successful");
MDC.clear();
Go (Zap)
logger.Info("user authentication",
zap.String("user_id", sanitize(userID)),
zap.String("action", "login"),
zap.Bool("success", true),
)
TypeScript (Winston)
logger.info('user authentication', {
userId: sanitize(userId),
action: 'login',
success: true,
timestamp: new Date().toISOString()
});
Log Format Requirements
A secure log entry should include:
| Field | Purpose |
|---|
| Timestamp | When (ISO 8601) |
| Level | Severity (INFO, WARN, ERROR) |
| Source | Where (service, file, function) |
| User | Who (user ID, not PII) |
| Action | What happened |
| Resource | What was accessed |
| Outcome | Success/failure |
| Request ID | Correlation |
| IP Address | Origin |
Example Secure Log Format
{
"timestamp": "2025-01-15T10:30:00Z",
"level": "INFO",
"service": "auth-service",
"event": "user_login",
"user_id": "usr_12345",
"action": "authenticate",
"outcome": "success",
"request_id": "req_abc123",
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0..."
}
Verification Checklist
CWE References
| CWE | Name | Example |
|---|
| CWE-117 | Log Injection | Newlines in log messages |
| CWE-223 | Omission of Info | Missing auth failure logs |
| CWE-532 | Secrets in Logs | Passwords logged |
| CWE-778 | Insufficient Logging | No audit trail |