Logging Failures
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.
Best use case
Logging Failures is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
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.
Teams using Logging Failures should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/logging-failures/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How Logging Failures Compares
| Feature / Agent | Logging Failures | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
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.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# 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
```bash
# String concatenation in logs
grep -rniE "logging\.(info|debug|error|warn).*\+|logger\.(info|debug|error|warn).*\+" --include="*.py"
# f-string/format in logs with user input
grep -rniE "logging\.(info|debug|error|warn).*f['\"]|logger\..*\.format\(" --include="*.py"
```
**Vulnerable**:
```python
# VULNERABLE: User input directly in log
logger.info(f"User login: {request.form['username']}") # Can inject newlines
```
**Secure**:
```python
# SAFE: Structured logging
logger.info("User login", extra={"username": sanitize(username)})
```
#### Java
```bash
# String concatenation in logs
grep -rniE "log\.(info|debug|error|warn).*\+|logger\.(info|debug|error|warn).*\+" --include="*.java"
# Format with user input
grep -rniE "String\.format.*log|log.*String\.format" --include="*.java"
```
**Vulnerable**:
```java
// VULNERABLE: Direct concatenation
logger.info("User login: " + username); // Can inject newlines
```
**Secure**:
```java
// SAFE: Parameterized logging
logger.info("User login: {}", sanitize(username));
```
#### Go
```bash
# Printf-style logging with user input
grep -rniE "log\.Printf|log\.Print.*\+" --include="*.go"
# Zap/logrus with user input
grep -rniE "zap\.String.*request|logrus\.WithField.*request" --include="*.go"
```
**Vulnerable**:
```go
// VULNERABLE: Direct formatting
log.Printf("User login: %s", userInput) // Can inject newlines
```
**Secure**:
```go
// SAFE: Structured logging
logger.Info("user login", zap.String("username", sanitize(username)))
```
#### TypeScript
```bash
# Console/logger with concatenation
grep -rniE "console\.(log|info|error|warn).*\+|logger\.(log|info|error|warn).*\+" --include="*.ts"
```
#### PHP
```bash
# error_log with user input
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
```bash
# Find auth functions without logging
grep -rniE "def (login|authenticate|authorize|check_permission)" --include="*.py" -A 10 | grep -v "log\."
# Find exception handlers without logging
grep -rniE "except.*:|catch\s*\(" --include="*.py" --include="*.java" -A 5 | grep -v "log\|logger"
# Find permission checks without logging
grep -rniE "has_permission|is_admin|check_role" --include="*.go" --include="*.py" --include="*.java" -A 5 | grep -v "log"
```
### What to Check
```bash
# Authentication logging
grep -rniE "login|authenticate|logout" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php" | xargs -I {} sh -c 'grep -l "log" {} || echo "MISSING: {}"'
# Failed access logging
grep -rniE "forbidden|unauthorized|access.*denied" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
# Data modification logging
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
```bash
# Password in logs
grep -rniE "log.*(password|passwd|pwd|secret|token|api_key|apikey|credential)" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
# Request body logging (may contain secrets)
grep -rniE "log.*request\.body|log.*req\.body|log.*getBody" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
# Full object logging
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
```python
# Python - Redact sensitive fields
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))
```
```go
// Go - Redact sensitive fields
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
```bash
# Predictable log file paths
grep -rniE "logfile\s*=|LOG_FILE\s*=|log_path\s*=" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php" --include="*.env"
# User-controlled log paths
grep -rniE "log.*request\.(path|param|query)" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
# Log rotation without integrity
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
```bash
# Check for alerting configuration
grep -rniE "alert|notify|pagerduty|slack.*webhook|email.*notify" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.yaml" --include="*.json"
# Check for threshold-based alerts
grep -rniE "threshold|rate_limit|max_attempts|lockout" --include="*.go" --include="*.py" --include="*.java" --include="*.ts" --include="*.php"
```
---
## Language-Specific Secure Logging
### Python (structlog)
```python
import structlog
logger = structlog.get_logger()
# Structured with automatic sanitization
logger.info(
"user_login",
username=sanitize(username),
ip_address=request.remote_addr,
success=True
)
```
### Java (SLF4J + Logback)
```java
// Use MDC for structured context
MDC.put("userId", sanitize(userId));
MDC.put("action", "login");
logger.info("User authentication successful");
MDC.clear();
```
### Go (Zap)
```go
logger.Info("user authentication",
zap.String("user_id", sanitize(userID)),
zap.String("action", "login"),
zap.Bool("success", true),
)
```
### TypeScript (Winston)
```typescript
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
```json
{
"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
- [ ] Log injection prevented (sanitized input)
- [ ] Authentication events logged
- [ ] Authorization failures logged
- [ ] Data access logged
- [ ] Sensitive data redacted
- [ ] Logs written to secure location
- [ ] Log integrity protected
- [ ] Alerting configured for critical events
- [ ] Log retention policy defined
---
## 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 |