VNX-431: Missing Handler
Reports Java errors with no handler: a WEB-INF/web.xml with no error page for uncaught exceptions, and CompletableFuture.runAsync/supplyAsync or ExecutorService.submit whose future is discarded with no exception handler, so the task's exception is silently lost.
| Field | Value |
|---|---|
| Rule ID | VNX-431 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Java |
| CWE | CWE-431 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L |
| Tags | missing-handler error-handling cwe-431 |
| Source | internal/sast/rules/vnx-431.rego |
Overview
VNX-431 maps to CWE-431: Missing Handler. An error that something is expected to handle has no handler at all. In a servlet application, an uncaught exception then reaches the container’s default error page, which shows the stack trace and server version. In concurrent code, an exception thrown by a task whose future nobody keeps is captured in that future and never seen.
What Gets Flagged
- A
web.xmlwhose<web-app>has no<error-page>forjava.lang.Throwable/Exception/RuntimeException, none for error code 500, and no default<error-page>with only a<location>(the<web-app>line is reported). CompletableFuture.runAsync/supplyAsyncused as a statement (future not assigned, returned or passed on) whose chain has noexceptionally,handle,whenComplete,joinorget.executor.submit(...)used as a statement, whereexecutoris declared as anExecutorService,ScheduledExecutorService,ThreadPoolExecutororForkJoinPool, or assigned fromExecutors.*.
CompletableFuture.runAsync(() -> store.save(r.rebuild()), pool); // FLAGGED
workers.submit(() -> smtp.deliver(m)); // FLAGGED
CompletableFuture.runAsync(task, pool).exceptionally(ex -> { log.error("failed", ex); return null; }); // not flagged
pool.execute(task); // not flagged: reaches the uncaught-exception handler
<web-app ...> <!-- FLAGGED when no error page covers uncaught exceptions -->
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error</location>
</error-page> <!-- with this, not flagged -->
</web-app>
Not reported: a task whose body catches Exception or Throwable, a kept future, execute(), test sources, comments. A broad @ExceptionHandler(Exception.class) is a handler and is not reported. The rule is evaluated only when the scanned tree also contains Java source, so a web.xml scanned alone, with no .java file beside it, is not read.
Remediation
- Declare
<error-page>entries forjava.lang.Throwable(and 500) pointing at a generic page. - Keep the future and attach
exceptionally/handle/whenComplete, or catch inside the task. - Use
execute()for fire-and-forget work so the thread’s uncaught-exception handler sees failures.
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-431
// nosec vnx-431
Or record an ignore rule: vulnetix ignore add --rule vnx-431 --reason "...". See Suppressing findings.