Get the FREE Ultimate OpenClaw Setup Guide →

Logging Failures

Scanned
npx machina-cli add skill allsmog/vuln-scout/logging-failures --openclaw
Files (1)
SKILL.md
10.6 KB

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 2025 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

# 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:

# VULNERABLE: User input directly in log
logger.info(f"User login: {request.form['username']}")  # Can inject newlines

Secure:

# SAFE: Structured logging
logger.info("User login", extra={"username": sanitize(username)})

Java

# 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:

// VULNERABLE: Direct concatenation
logger.info("User login: " + username);  // Can inject newlines

Secure:

// SAFE: Parameterized logging
logger.info("User login: {}", sanitize(username));

Go

# 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:

// VULNERABLE: Direct formatting
log.Printf("User login: %s", userInput)  // Can inject newlines

Secure:

// SAFE: Structured logging
logger.Info("user login", zap.String("username", sanitize(username)))

TypeScript

# Console/logger with concatenation
grep -rniE "console\.(log|info|error|warn).*\+|logger\.(log|info|error|warn).*\+" --include="*.ts"

PHP

# 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 CategorySpecific Events
AuthenticationLogin success/failure, logout, password change
AuthorizationAccess denied, privilege escalation attempts
Input ValidationRejected/suspicious input
SessionSession creation, destruction, timeout
Data AccessSensitive data read/write/delete
ConfigurationSettings changes, feature toggles
ErrorsExceptions, failures (without stack traces)

Detection Patterns

# 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

# 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

# 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 - 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 - 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

# 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

EventAlert Priority
Multiple failed loginsHIGH
Admin actionsMEDIUM
Privilege escalationCRITICAL
Sensitive data accessHIGH
Configuration changesMEDIUM
Error rate spikeHIGH
Unusual access patternsMEDIUM

Detection Patterns

# 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)

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)

// Use MDC for structured context
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:

FieldPurpose
TimestampWhen (ISO 8601)
LevelSeverity (INFO, WARN, ERROR)
SourceWhere (service, file, function)
UserWho (user ID, not PII)
ActionWhat happened
ResourceWhat was accessed
OutcomeSuccess/failure
Request IDCorrelation
IP AddressOrigin

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

  • 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

CWENameExample
CWE-117Log InjectionNewlines in log messages
CWE-223Omission of InfoMissing auth failure logs
CWE-532Secrets in LogsPasswords logged
CWE-778Insufficient LoggingNo audit trail

Source

git clone https://github.com/allsmog/vuln-scout/blob/main/whitebox-pentest/skills/logging-failures/SKILL.mdView on GitHub

Overview

This skill helps detect log injection, insufficient logging of security events, and secrets in logs during whitebox pentesting. It aligns with OWASP A09 and CWE-117, CWE-223, CWE-532, and CWE-778, and provides practical detection patterns and concrete examples across languages.

How This Skill Works

It analyzes code for unsanitized user input written to logs, provides language-specific detection patterns and commands, and contrasts vulnerable versus secure logging patterns. It also highlights which security events should be logged to maintain a complete audit trail.

When to Use It

  • Reviewing logging implementations for potential log injection and output neutralization issues
  • Auditing security event logging to ensure traceability and completeness
  • Searching for secrets or sensitive data exposed in logs
  • Verifying audit trails for authentication, authorization, session, and data access events
  • Assessing risk of log tampering and insufficient logging during pentesting

Quick Start

  1. Step 1: Identify inputs and events that are logged, focusing on authentication, authorization, session, and data access
  2. Step 2: Apply language-specific safe logging patterns (structured logging, redaction, and sanitization)
  3. Step 3: Run the provided detection commands and run an audit to confirm log integrity and coverage of critical events

Best Practices

  • Sanitize user input before writing to logs
  • Use structured logging with redacted or sanitized fields
  • Avoid logging secrets; redact or encrypt sensitive data
  • Prefer parameterized or structured logging instead of string concatenation
  • Regularly test logs for completeness and integrity, including tamper-evidence and retention controls

Example Use Cases

  • Python vulnerable: direct user input appears in logs via f-string-style logging
  • Python secure: use structured logging and log extra sanitized fields
  • Java vulnerable: log calls concatenate strings with user input
  • Java secure: use parameterized logging with sanitized input
  • Go vulnerable: direct formatting of user input in logs vs Go-style structured logging

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers