OWASP Top 10:2025 Technical Verification Standard
WebOTG Hub v4.2
WebOTG-EXP-001 • Exception Handling & Resilience Guide

A10:2025 — Mishandling of Exceptional Conditions

Mishandling of exceptional conditions occurs when software fails to properly handle unexpected errors, edge cases, partial failures, or network timeouts, resulting in unhandled state transitions, denial of service, or fail-open security bypasses.

OWASP Standard
A10:2025
Primary CWEs
CWE-754, CWE-703, CWE-248
Risk Severity
High (CVSS 7.5)
Verification Target
Fail-Safe, Graceful Recovery

01 Exception Mishandling Failure Modes

Exceptional condition flaws emerge when code paths do not account for unpredicted states or system faults:

  • Fail-Open Authorization: An authorization check throws a null pointer or database connection timeout, and the catching logic defaults to allowing access rather than denying it.
  • Unreleased Resources on Error: Unhandled exceptions before database transactions are committed or file locks/handles are released, leading to thread pool exhaustion and denial of service.
  • Partial State Mutation: Exception occurring midway through a multi-step financial transaction without transactional rollback, leaving accounts in an inconsistent state.
  • Silent Exception Swallowing: Empty catch (Exception e) {} blocks hiding upstream system errors.

02 Vulnerability Demonstration: Fail-Open Logic

Vulnerable Implementation: Fail-Open on Policy Error

vulnerable_policy.phpPHP
// VULNERABLE: Fail-Open logic on network timeout or service failure
function isActionAllowed($userId, $action) {
    try {
        $client = new AuthPolicyServiceClient();
        $response = $client->checkPermission($userId, $action);
        return $response->isAllowed();
    } catch (Exception $e) {
        // CATASTROPHIC FLAW: Fails open to prevent "blocking users" on policy server errors
        error_log("Policy server down: " . $e->getMessage());
        return true; // Grants access to all restricted resources!
    }
}

03 Audit & Static Code Analysis Rules

Anti-Pattern AST / Grep Pattern Remediation
Fail-Open Return catch\s*\(.*\)\s*\{\s*return\s+true; Enforce Fail-Closed (return false)
Empty Catch Block catch\s*\([^\)]+\)\s*\{\s*\} Explicit handling, logging, and error state propagation

04 Hardened Fail-Safe Exception Pattern

Fail-Closed Architecture with Transactional Rollbacks

secure_exception_engine.phpPHP 8+
class AccountTransferService {
    private PDO $db;

    public function transferFunds(int $fromId, int $toId, int $amountCents): bool {
        if ($amountCents <= 0) {
            throw new InvalidArgumentException("Transfer amount must be positive");
        }

        $this->db->beginTransaction();

        try {
            // 1. Deduct funds
            $stmt = $this->db->prepare("UPDATE accounts SET balance = balance - :amt WHERE id = :id AND balance >= :amt");
            $stmt->execute([':amt' => $amountCents, ':id' => $fromId]);

            if ($stmt->rowCount() === 0) {
                throw new InsufficientFundsException("Insufficient balance");
            }

            // 2. Credit destination
            $stmt = $this->db->prepare("UPDATE accounts SET balance = balance + :amt WHERE id = :id");
            $stmt->execute([':amt' => $amountCents, ':id' => $toId]);

            $this->db->commit();
            return true;
        } catch (Throwable $e) {
            // Roll back completely on ANY failure
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log("Transaction failed: " . $e->getMessage());
            return false; // Fail-Closed
        }
    }
}

05 Verification & Compliance Checklist

Resilience Gate Standard Status
Fail-Closed Architecture All authorization checks fail closed (deny access) on exception. Enforced
Database Transactions Atomic multi-statement mutations wrapped in rollback blocks. Enforced
No Empty Catches Zero swallowed exceptions across all service layers. Enforced