Unsafe Control Flow Inside Finally

ID

javascript.unsafe_finally

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

reliability, suspicious-comparison

Description

Reports return, throw, break, and continue statements inside a finally block. Such statements override any pending exception or return value from the surrounding try / catch, silently swallowing errors and producing behaviour that depends on subtle execution-order details.

Rationale

finally runs after a possibly-thrown exception or a return value is committed but before it propagates. A return / throw / break / continue inside finally replaces the pending result, hiding the original outcome:

// Bad - the thrown error is swallowed; the function returns "swallowed"
function f() {
  try {
    throw new Error("oops");
  } finally {
    return "swallowed";
  }
}

Statements that exit a function or loop declared inside the finally block are safe — they don’t escape the finally.

Remediation

Move the control flow out of finally, or restructure so that finally only contains side-effecting cleanup that doesn’t return / throw.

// Good
function f() {
  try {
    return doWork();
  } finally {
    cleanup();
  }
}