Weakness reference
CWE-392

Missing Report of Error Condition

This weakness occurs when software encounters an error but silently fails to log, report, or otherwise communicate that something went wrong. Without error…

01Summary

This weakness occurs when software encounters an error but silently fails to log, report, or otherwise communicate that something went wrong. Without error reporting, administrators and security tools cannot detect problems, investigate incidents, or respond to attacks in progress. This silence can mask security breaches, data corruption, and system failures until damage is severe.

02How It Happens

Applications encounter errors constantly—database connection failures, file access denials, invalid input, permission checks that fail. Developers often catch these errors in code but then do nothing with them: they suppress the exception, ignore the return value, or log to a stream that is never monitored. The application continues as if nothing happened, or fails in an unpredictable way. Without a clear error signal, security events (failed authentication attempts, unauthorized access, injection attacks) blend into normal operation and go unnoticed.

03Real-World Impact

Silent failures create a blind spot in security monitoring. An attacker may attempt SQL injection, privilege escalation, or account enumeration repeatedly without triggering any alert. A legitimate user's data may be corrupted or lost without anyone knowing. System misconfigurations or compromised components may operate undetected for weeks. When a breach is eventually discovered through other means, the lack of logs makes forensic investigation nearly impossible, delaying incident response and increasing the scope of damage.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import sqlite3

def authenticate_user(username, password):
    try:
        conn = sqlite3.connect('users.db')
        cursor = conn.cursor()
        cursor.execute(
            "SELECT id FROM users WHERE username = ? AND password = ?",
            (username, password)
        )
        result = cursor.fetchone()
        return result is not None
    except Exception:
        pass  # Error silently ignored
    return False

Why it's vulnerable:
If the database is unavailable, corrupted, or under attack, the exception is caught and discarded. The function returns False, making it indistinguishable from a failed login attempt. No one knows the authentication system is broken.

Fixed pattern
import sqlite3
import logging

logger = logging.getLogger(__name__)

def authenticate_user(username, password):
    try:
        conn = sqlite3.connect('users.db')
        cursor = conn.cursor()
        cursor.execute(
            "SELECT id FROM users WHERE username = ? AND password = ?",
            (username, password)
        )
        result = cursor.fetchone()
        return result is not None
    except sqlite3.DatabaseError as e:
        logger.error(f"Database error during authentication: {e}")
        raise
    except Exception as e:
        logger.critical(f"Unexpected error during authentication: {e}")
        raise
Vulnerable pattern
<?php
function process_payment($user_id, $amount) {
    $conn = mysqli_connect('localhost', 'user', 'pass', 'shop_db');
    
    if (!$conn) {
        // Connection failed, but no error logged or reported
    }
    
    $query = "UPDATE accounts SET balance = balance - $amount WHERE id = $user_id";
    $result = mysqli_query($conn, $query);
    
    if (!$result) {
        // Query failed, but error is ignored
    }
    
    return true;
}
?>

Why it's vulnerable:
Database connection and query failures are not logged or reported. A payment may fail silently, leaving the user's balance unchanged while the transaction is recorded elsewhere, or vice versa. No audit trail exists.

Fixed pattern
<?php
function process_payment($user_id, $amount) {
    $conn = mysqli_connect('localhost', 'user', 'pass', 'shop_db');
    
    if (!$conn) {
        error_log("Payment processing failed: database connection error");
        throw new Exception("Payment system unavailable");
    }
    
    $query = "UPDATE accounts SET balance = balance - ? WHERE id = ?";
    $stmt = $conn->prepare($query);
    
    if (!$stmt) {
        error_log("Payment query preparation failed: " . $conn->error);
        throw new Exception("Payment system error");
    }
    
    $stmt->bind_param("di", $amount, $user_id);
    if (!$stmt->execute()) {
        error_log("Payment execution failed for user $user_id: " . $stmt->error);
        throw new Exception("Payment processing failed");
    }
    
    return true;
}
?>

05Prevention Checklist

Log all errors and exceptions
— use a centralized logging system (syslog, ELK, CloudWatch) and ensure logs are retained and monitored.
Distinguish error severity
— use appropriate log levels (ERROR, CRITICAL, WARNING) so that security-relevant failures stand out.
Never silently catch and ignore exceptions
— if you catch an exception, log it and either re-throw it or fail safely; never pretend it didn't happen.
Monitor and alert on error thresholds
— set up alerts for repeated authentication failures, database errors, or permission denials that may indicate an attack.
Include context in error messages
— log the user, timestamp, operation, and reason for failure; avoid generic "error occurred" messages.
Test error paths
— verify that your error handling code actually runs and logs correctly; don't assume it works if you've never triggered it.

06Signs You May Already Be Affected

Review your application logs for gaps or missing entries around security-sensitive operations (login, file access, API calls, database queries). If you cannot find a log entry for an action you know occurred, or if error logs are empty despite occasional system issues, error reporting may be disabled or suppressed. Check whether your monitoring system receives alerts for failed authentication attempts, database errors, or permission denials; silence in these areas is a red flag.