Detection of Error Condition Without Action

Description

Detection of Error Condition Without Action is a vulnerability that occurs when software detects a specific error but takes no actions to handle it. This includes empty catch blocks, ignored return values after checking them, and exception handlers that suppress errors silently. When errors are detected but not acted upon, the program continues execution in an unexpected or invalid state, potentially leading to security vulnerabilities, crashes, or data corruption.

Risk

Ignoring detected errors leaves systems in unexpected states that attackers can exploit. Memory allocation failures that are detected but ignored lead to null pointer dereferences or use of uninitialized memory. File operation errors that are silently suppressed may result in incomplete data processing or resource leaks. Security checks that detect failures but continue anyway negate the purpose of the check. Attackers can deliberately trigger error conditions to force the application into vulnerable states. The silent nature of these failures makes debugging difficult and may hide active exploitation.

Solution

Properly handle each exception by ensuring all detected errors are addressed so system state remains predictable. When functions return errors, either fix the issue and retry, alert users while continuing gracefully, or alert and terminate gracefully with proper cleanup. Never use empty catch blocks - at minimum, log the error for debugging purposes. Use extensive testing techniques including ad hoc testing, equivalence partitioning, robustness testing, mutation testing, and fuzzing to discover unhandled errors. Establish coding standards that prohibit empty exception handlers.

Common Consequences

ImpactDetails
IntegrityScope: Integrity

An attacker could exploit ignored error conditions to place systems in unexpected states.
OtherScope: Other

Altered execution logic - Unintended code paths may execute, enabling harmful behavior.

Example Code

Vulnerable Code

// Vulnerable: Error detected but no action taken
void vulnerable_read_file(const char *filename) {
    FILE *f = fopen(filename, "r");
    char buffer[1024];

    // Vulnerable: Error detected but ignored
    if (f == NULL) {
        // Empty block - error detected but no action!
    }

    // Continues with NULL file pointer - crash or undefined behavior
    fread(buffer, 1, sizeof(buffer), f);
    fclose(f);
}

// Vulnerable: Memory allocation failure ignored
void vulnerable_process_data(size_t size) {
    char *buffer = malloc(size);

    if (buffer == NULL) {
        // Vulnerable: Detected but no action
        perror("malloc failed");
        // Falls through and uses NULL pointer!
    }

    memset(buffer, 0, size);  // Crash!
}
// Vulnerable: Empty catch block
public class VulnerableFileReader {

    public String readFile(String path) {
        FileInputStream fis = null;
        String content = null;

        try {
            fis = new FileInputStream(path);
            byte[] data = new byte[fis.available()];
            fis.read(data);
            content = new String(data);
        } catch (IOException e) {
            // Vulnerable: Exception caught but completely ignored!
            // No logging, no notification, no handling
        }

        return content;  // May return null unexpectedly
    }

    public void processConfig(String configPath) {
        try {
            Config config = loadConfig(configPath);
            applyConfig(config);
        } catch (ConfigException e) {
            // Vulnerable: Silently ignore config errors
            // System continues with default/old config
        }
    }
}

// Vulnerable: Return value checked but not acted upon
public class VulnerableAuth {
    public void authenticate(String username, String password) {
        boolean valid = validateCredentials(username, password);

        if (!valid) {
            // Vulnerable: Detected invalid credentials but continues!
            logger.warn("Invalid credentials");
            // Falls through to allow access
        }

        grantAccess(username);
    }
}
# Vulnerable: Exception caught but ignored
def vulnerable_connect_db():
    connection = None

    try:
        connection = database.connect()
    except DatabaseError as e:
        pass  # Vulnerable: Error silently ignored!

    # Proceeds with None connection
    return connection.execute("SELECT * FROM users")  # Crash!

# Vulnerable: Error logged but execution continues unsafely
def vulnerable_write_file(filename, data):
    try:
        with open(filename, 'w') as f:
            f.write(data)
    except IOError as e:
        print(f"Write failed: {e}")
        # Vulnerable: Continues as if write succeeded

    # Report success even on failure
    notify_success("File written: " + filename)

Fixed Code

// Fixed: Proper error handling with return codes
int secure_read_file(const char *filename, char *buffer, size_t bufsize) {
    FILE *f = fopen(filename, "r");

    // Fixed: Return error code on failure
    if (f == NULL) {
        fprintf(stderr, "Failed to open file: %s\n", filename);
        return -1;
    }

    size_t bytes_read = fread(buffer, 1, bufsize - 1, f);

    if (ferror(f)) {
        fprintf(stderr, "Error reading file: %s\n", filename);
        fclose(f);
        return -1;
    }

    buffer[bytes_read] = '\0';
    fclose(f);
    return 0;
}

// Fixed: Handle allocation failure properly
int secure_process_data(size_t size) {
    char *buffer = malloc(size);

    // Fixed: Return error or abort on allocation failure
    if (buffer == NULL) {
        perror("malloc failed");
        return -1;  // Or abort() for critical failures
    }

    memset(buffer, 0, size);
    process_buffer(buffer, size);
    free(buffer);
    return 0;
}
// Fixed: Proper exception handling
public class SecureFileReader {

    public String readFile(String path) throws IOException {
        // Fixed: Let exception propagate if caller can't handle
        try (FileInputStream fis = new FileInputStream(path)) {
            byte[] data = new byte[fis.available()];
            fis.read(data);
            return new String(data);
        }
    }

    public String readFileWithFallback(String path) {
        try (FileInputStream fis = new FileInputStream(path)) {
            byte[] data = new byte[fis.available()];
            fis.read(data);
            return new String(data);
        } catch (IOException e) {
            // Fixed: Log error and provide fallback
            logger.error("Failed to read file: " + path, e);
            return getDefaultContent();  // Or throw runtime exception
        }
    }

    public void processConfig(String configPath) throws ConfigException {
        try {
            Config config = loadConfig(configPath);
            applyConfig(config);
        } catch (ConfigException e) {
            // Fixed: Log, alert, and re-throw
            logger.error("Config load failed", e);
            alertAdmin("Configuration error: " + e.getMessage());
            throw e;  // Let caller decide how to proceed
        }
    }
}

// Fixed: Act on detected authentication failure
public class SecureAuth {
    public void authenticate(String username, String password)
            throws AuthenticationException {
        boolean valid = validateCredentials(username, password);

        if (!valid) {
            // Fixed: Take action on invalid credentials
            logger.warn("Invalid credentials for user: " + username);
            auditLog.logFailedAttempt(username);
            throw new AuthenticationException("Invalid credentials");
        }

        grantAccess(username);
    }
}
# Fixed: Proper exception handling
def secure_connect_db():
    try:
        connection = database.connect()
        return connection
    except DatabaseError as e:
        # Fixed: Log and re-raise or return sentinel value
        logger.error(f"Database connection failed: {e}")
        raise  # Or return None with clear documentation

# Fixed: Handle file write errors properly
def secure_write_file(filename, data):
    try:
        with open(filename, 'w') as f:
            f.write(data)
    except IOError as e:
        logger.error(f"Write failed: {e}")
        # Fixed: Don't report success, propagate error
        raise WriteError(f"Failed to write {filename}") from e

    # Only notify success if write actually succeeded
    notify_success(f"File written: {filename}")

# Fixed: Return status to caller
def secure_process_data(data):
    try:
        result = process(data)
        return {"success": True, "result": result}
    except ProcessingError as e:
        logger.error(f"Processing failed: {e}")
        # Fixed: Return error status instead of silently continuing
        return {"success": False, "error": str(e)}

CVE Examples

  • CVE-2022-21820 — GPU data center manager ignores malformed request errors, causing memory corruption.

References

  1. MITRE Corporation. "CWE-390: Detection of Error Condition Without Action." https://cwe.mitre.org/data/definitions/390.html
  2. CERT. "ERR00-C. Adopt and implement a consistent and comprehensive error-handling policy."