VNX-391: Unchecked Error Condition
An exception is caught and silently discarded: a Java catch block holding only a TODO or auto-generated comment (plainly empty ones are reported by VNX-390), or a broad Python except whose whole body is pass.
| Field | Value |
|---|---|
| Rule ID | VNX-391 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Java, Python |
| CWE | CWE-391 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | error-handling cwe-391 |
| Source | internal/sast/rules/vnx-391.rego |
Overview
VNX-391 maps to CWE-391: Unchecked Error Condition. It reports an exception that is caught and then thrown away. In Java that is a catch block which holds only a TODO/FIXME or auto-generated comment (beside blanks or a discarded e.toString()), or an empty or no-op body that runs longer than VNX-390 looks. A Java catch that is plainly empty (on one line, across a few blank lines, or with the brace on its own line) or whose only statement is a discarded e.toString()/e.getMessage() is reported by VNX-390 instead: it is the same defect, and CWE-390 (Detection of Error Condition Without Action) names it more exactly, so each such catch is one finding. In Python it is a bare except:, except Exception or except BaseException (alone or in a tuple) whose whole body is pass or ....
Not reported: a handler that logs, rethrows, returns or records anything; a Java catch variable named ignored, ignore, expected or unused (an explicit discard); a body with an explanatory comment, or a Python pass or except line carrying a trailing comment other than TODO/FIXME (# nosec, # noqa, a reason), which are documented decisions; a Python except of a specific type such as ImportError or KeyError; contextlib.suppress; test files, comments and strings.
Why This Matters
A swallowed exception turns a failure into silent success. The caller carries on with half-written data, a missing configuration or an unauthenticated session, and nothing in the logs says why. Broad handlers also swallow programming errors, so bugs that would have crashed loudly in testing hide in production.
What Gets Flagged
} catch (IOException e) { // FLAGGED
// TODO handle this
}
} catch (Exception e) { // FLAGGED
// Auto-generated catch block
}
try {
ledger.write(invoice);
} catch (Exception e) {} // reported by VNX-390, not here
try:
os.remove(path)
except Exception: # FLAGGED
pass
Remediation
- Catch the specific exception the call can raise, and handle it: retry, fall back, or return an error the caller checks.
- If the failure is genuinely harmless, log it at debug level or name the variable
ignoredand add a comment saying why. - In Python, prefer
contextlib.suppress(SpecificError)for a deliberate, narrow discard.
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-391
// nosec vnx-391
Or record an ignore rule: vulnetix ignore add --rule vnx-391 --reason "...". See Suppressing findings.