Safeguard
Application Security•

CWE-705 Incorrect Control Flow Scoping: The Goto Fail Family

Control returns to the wrong place after a task or an error, as in Apple's goto fail bug and an uncaught exception boot loop. CWE-705 explained.

Safeguard Security Team
3 min read

CWE-705, Incorrect Control Flow Scoping, describes a product that does not return control to the proper location after finishing a task or detecting an unusual condition. The consequence MITRE records is altered execution logic. It is not language specific.

Two things can go wrong. Control can skip past code that should have run, or land somewhere it should never have been.

How it happens

CVE-2014-1266 is Apple's well known "goto fail" bug. An incorrect goto in an SSL product bypassed certificate validation, enabling an adversary-in-the-middle attack. MITRE shows it as a chain from this weakness into the weakness of an unintended path.

The shape was a duplicated line. An illustration of the pattern, not the original source:

// Vulnerable: the second goto is outside the if, so it always runs
if ((err = check_hash(ctx)) != 0)
    goto fail;
    goto fail;                 // always taken
if ((err = check_signature(ctx)) != 0)   // never reached
    goto fail;
fail:
    return err;                // err is still 0 here: success

The skipped signature check leaves err at zero, so the function returns success.

CVE-2023-21087 is a different flavor: Java code in a smartphone OS can encounter a boot loop due to an uncaught exception. An error was detected, control went to no handler, and the system restarted over and over.

What an attacker gains

Altered logic means whatever the skipped or misdirected code protected. In one case, a trusted connection with an unverified peer. In the other, a device that will not start.

How to find it

MITRE notes static analysis can find some instances by modelling data and control flow. Unreachable code warnings and misleading indentation warnings catch the goto fail shape. Test failure paths so that each check is shown to fail when it should.

How to fix it

  1. Always use braces on conditionals so an added line cannot slip out of the block.
  2. Turn on warnings for unreachable code and misleading indentation, and fail the build on them.
  3. Initialize result variables to failure, not success.
  4. Catch exceptions at a boundary that decides what the failure means.
  5. Write a test per check that proves a bad input is rejected.
int err = -1;                 // default is failure
if ((err = check_hash(ctx)) != 0) { goto fail; }
if ((err = check_signature(ctx)) != 0) { goto fail; }
err = 0;
fail:
    return err;

Quick check

Why does initializing to failure help?

If control skips a check, the function still returns failure instead of a stale success value.

What caused the boot loop in CVE-2023-21087?

An uncaught exception in Java code, so control had no proper place to return to.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.