Weakness reference
CWE-478

Missing Default Case in Switch Statement

A switch statement without a default case leaves the program unable to handle unexpected input values. When a value doesn't match any case, execution may…

01Summary

A switch statement without a default case leaves the program unable to handle unexpected input values. When a value doesn't match any case, execution may continue silently or behave unpredictably, leading to logic errors, security bypasses, or data corruption. This weakness is especially dangerous in security-critical code paths where all possible inputs must be explicitly accounted for.

02How It Happens

Switch statements are designed to route execution based on the value of a variable. Each case handles a specific value; the default case is meant to catch anything that doesn't match. When a developer omits the default case, they assume all possible inputs will be covered by the explicit cases. However, this assumption often fails: user input may be malformed, an enum may be extended in the future, or an attacker may supply an unexpected value. Without a default handler, the program either falls through to the next statement or behaves in an unintended way, potentially skipping critical validation or security checks.

03Real-World Impact

Missing default cases can lead to authentication bypasses (a user role not explicitly handled defaults to an unintended permission level), incorrect business logic (a transaction type not covered skips validation), or information disclosure (an error condition is silently ignored instead of being logged). In web applications, this often manifests as a request parameter being processed incorrectly or a state machine advancing to an invalid state. The impact ranges from minor logic bugs to serious security flaws, depending on what the unhandled case should have done.

04Vulnerable & Fixed Patterns

Vulnerable pattern
def process_user_action(action):
    if action == "create":
        return create_resource()
    elif action == "read":
        return read_resource()
    elif action == "delete":
        return delete_resource()
    # No else clause — unexpected action silently returns None

Why it's vulnerable:
If action contains an unexpected value (e.g., "admin_override" or a typo), the function returns None without logging or raising an error. A caller may misinterpret this as success, or the application may crash downstream when trying to use the result.

Fixed pattern
def process_user_action(action):
    if action == "create":
        return create_resource()
    elif action == "read":
        return read_resource()
    elif action == "delete":
        return delete_resource()
    else:
        raise ValueError(f"Unknown action: {action}")
Vulnerable pattern
switch ($_GET['role']) {
    case 'admin':
        $permissions = ['read', 'write', 'delete'];
        break;
    case 'editor':
        $permissions = ['read', 'write'];
        break;
    case 'viewer':
        $permissions = ['read'];
        break;
    // No default — unknown role leaves $permissions undefined
}
apply_permissions($permissions);

Why it's vulnerable:
If $_GET['role'] is set to an unexpected value (or is missing), $permissions is never defined. The subsequent call to apply_permissions() may fail, or $permissions may retain a value from a previous request, leading to privilege escalation or undefined behavior.

Fixed pattern
switch ($_GET['role'] ?? '') {
    case 'admin':
        $permissions = ['read', 'write', 'delete'];
        break;
    case 'editor':
        $permissions = ['read', 'write'];
        break;
    case 'viewer':
        $permissions = ['read'];
        break;
    default:
        error_log("Unknown role: " . $_GET['role']);
        $permissions = [];
        break;
}
apply_permissions($permissions);

05Prevention Checklist

Always include a default case in every switch statement, even if you believe all cases are covered.
In the default case, either raise an exception, log a warning, or set a safe fallback value — never silently continue.
Use static analysis tools (linters, type checkers) to flag switch statements without defaults.
When switch statements depend on enums or a fixed set of values, document the assumption and review it during code review.
For security-critical decisions (authentication, authorization, transaction types), explicitly validate the input before the switch and reject unknown values outright.
Consider using a lookup table or dictionary instead of a switch statement if the set of cases is large or frequently changing.

06Signs You May Already Be Affected

Review your application logs for unexpected behavior: requests that should have been rejected but were silently ignored, or state transitions that don't match your documented flow. Check for undefined variable warnings or null pointer exceptions that occur only under specific input conditions. If you find switch statements in your codebase without default cases, especially in authentication, authorization, or payment processing code, prioritize adding explicit handling for unexpected values.