Unchecked Error Condition

Description

Unchecked Error Condition is a vulnerability that occurs when programmers fail to properly check or handle exceptions and error conditions. This weakness arises from flawed assumptions: either that an operation cannot fail, or that failures don't matter. When exceptions are ignored or error conditions go unchecked, attackers can induce unexpected behavior that goes unnoticed. The program continues execution in a potentially invalid state, unaware that a critical operation has failed.

Risk

Ignoring exceptions and error conditions allows attackers to exploit the gap between expected and actual system states. Memory allocation failures, file operations, network communications, and authentication checks that silently fail leave applications vulnerable. Security controls that are bypassed due to unchecked errors may grant unauthorized access. Data corruption can occur when operations fail midway without proper handling. The silent nature of these failures makes them particularly dangerous as there's no logged evidence of the problem, hindering detection and forensic analysis.

Solution

Select programming languages that enforce compile-time exception handling to catch these issues during development. Catch all relevant exceptions and ensure that all exceptions are handled in a way that maintains predictable system state. Never leave catch blocks empty - at minimum log the error for debugging. Establish coding standards that require explicit error handling. Use static analysis tools to detect unchecked error conditions. Document which exceptions each function can throw and require callers to handle them. Consider using languages with checked exceptions or linters that warn about ignored errors.

Common Consequences

ImpactDetails
IntegrityScope: Integrity, Other

Varies by Context - Unexpected State, Altered Execution Logic. The system may enter an invalid state leading to unintended behaviors.

Example Code

Vulnerable Code

// Vulnerable: Exception caught but completely ignored
public class VulnerableExchange {

    public void performExchange() {
        try {
            doExchange();
        } catch (RareException e) {
            // Vulnerable: "this can never happen"
            // If it does happen, no one will ever know
        }

        // Continues as if exchange succeeded
        confirmExchange();
    }

    public void processFile(String path) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(path);
            processData(fis);
        } catch (FileNotFoundException e) {
            // Vulnerable: Silently ignored
        } catch (IOException e) {
            // Vulnerable: Also ignored
        }
        // May have processed no data at all
    }
}
// Vulnerable: Return value not checked
void vulnerable_operation() {
    char *data = malloc(1024);
    // Vulnerable: malloc can return NULL

    strcpy(data, get_user_input());  // Crash if NULL

    FILE *f = fopen("/tmp/data", "w");
    // Vulnerable: fopen can return NULL

    fwrite(data, 1, strlen(data), f);  // Crash if NULL
    fclose(f);
}

// Vulnerable: Error code ignored
void vulnerable_network() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    // Vulnerable: socket can return -1

    connect(sock, (struct sockaddr*)&addr, sizeof(addr));
    // Vulnerable: connect can fail

    send(sock, buffer, len, 0);
    // Vulnerable: send can fail partially or completely
}
# Vulnerable: Bare except that ignores all errors
def vulnerable_database_operation():
    try:
        connection = database.connect()
        cursor = connection.cursor()
        cursor.execute("INSERT INTO audit_log VALUES (?)", (event,))
        connection.commit()
    except:
        # Vulnerable: All exceptions silently swallowed
        pass

    # Continues as if logging succeeded
    perform_sensitive_operation()

Fixed Code

// Fixed: Proper exception handling
public class SecureExchange {

    public void performExchange() throws ExchangeException {
        try {
            doExchange();
        } catch (RareException e) {
            // Fixed: Log and handle or propagate
            logger.error("Rare exception during exchange", e);
            throw new ExchangeException("Exchange failed", e);
        }

        confirmExchange();
    }

    public void processFile(String path) throws FileProcessingException {
        try (FileInputStream fis = new FileInputStream(path)) {
            processData(fis);
        } catch (FileNotFoundException e) {
            // Fixed: Handle appropriately
            logger.error("File not found: " + path, e);
            throw new FileProcessingException("File not found: " + path, e);
        } catch (IOException e) {
            // Fixed: Handle I/O errors
            logger.error("Error reading file: " + path, e);
            throw new FileProcessingException("Failed to read file", e);
        }
    }
}
// Fixed: Check all return values
int secure_operation() {
    char *data = malloc(1024);
    // Fixed: Check malloc return
    if (data == NULL) {
        perror("malloc failed");
        return -1;
    }

    const char *input = get_user_input();
    if (input == NULL) {
        free(data);
        return -1;
    }
    strncpy(data, input, 1023);
    data[1023] = '\0';

    FILE *f = fopen("/tmp/data", "w");
    // Fixed: Check fopen return
    if (f == NULL) {
        perror("fopen failed");
        free(data);
        return -1;
    }

    size_t written = fwrite(data, 1, strlen(data), f);
    // Fixed: Check write success
    if (written != strlen(data)) {
        perror("fwrite incomplete");
        fclose(f);
        free(data);
        return -1;
    }

    fclose(f);
    free(data);
    return 0;
}

// Fixed: Check network operations
int secure_network() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    // Fixed: Check socket creation
    if (sock < 0) {
        perror("socket failed");
        return -1;
    }

    // Fixed: Check connect
    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("connect failed");
        close(sock);
        return -1;
    }

    // Fixed: Check send
    ssize_t sent = send(sock, buffer, len, 0);
    if (sent < 0) {
        perror("send failed");
        close(sock);
        return -1;
    }
    if (sent != len) {
        fprintf(stderr, "Partial send: %zd of %zu\n", sent, len);
    }

    close(sock);
    return 0;
}
# Fixed: Proper exception handling
def secure_database_operation():
    try:
        connection = database.connect()
        cursor = connection.cursor()
        cursor.execute("INSERT INTO audit_log VALUES (?)", (event,))
        connection.commit()
    except DatabaseError as e:
        # Fixed: Log specific error
        logger.error(f"Database operation failed: {e}")
        # Fixed: Don't proceed if audit logging failed
        raise AuditFailureException("Audit logging required") from e
    finally:
        if connection:
            connection.close()

    # Only proceed if logging succeeded
    perform_sensitive_operation()

CVE Examples

No specific CVEs are listed for this CWE. The vulnerability pattern appears in:

  • Applications with empty catch blocks
  • C code that ignores function return values
  • Systems that continue after security-critical operations fail

References

  1. MITRE Corporation. "CWE-391: Unchecked Error Condition." https://cwe.mitre.org/data/definitions/391.html