CWE-248 is simple to state: an exception is thrown from a function, but it is not caught. MITRE lists the languages C++, Java and C#.
How it happens
A request handler parses input. The parser throws on bad data. Nothing between the parser and the top of the thread handles it. Depending on the framework, the thread dies, the process exits, or a raw error page with internal details is returned.
// Vulnerable: bad input throws NumberFormatException with no handler
int page = Integer.parseInt(request.getParameter("page"));
// Fixed: handle the expected failure and respond cleanly
int page;
try {
page = Integer.parseInt(request.getParameter("page"));
} catch (NumberFormatException e) {
response.sendError(400, "Invalid page number");
return;
}
MITRE's observed examples:
- CVE-2023-41151: an OPC UA SDK server had an uncaught exception when a socket was blocked for writing but the server tried to send an error.
- CVE-2023-21087: Java code in a smartphone OS could hit a boot loop due to an uncaught exception.
What an attacker gains
The record lists availability and confidentiality: a crash, exit or restart, and read access to application data. An uncaught exception can place the system in a state that leads to a crash, exposure of sensitive information or other unintended behavior.
How to find it
MITRE lists automated static analysis. Beyond that:
- Send malformed input to every entry point and watch for stack traces or dropped connections.
- Review the code path from each input parser to the top of its thread.
- Check how your framework reports unhandled errors to clients.
How to fix it
The record has no mitigation list. Standard steps:
- Catch specific exceptions where you can recover, and respond with a clear error.
- Add a top level handler so nothing escapes a thread or request unhandled.
- Return generic messages to clients and write the detail to your logs.
- Make sure a failure cleans up what it started, such as locks and connections.
Where uncaught exceptions hide
The dangerous ones are rarely in the main path. They sit in error handling code, in background threads, in callbacks and in cleanup routines, which are the places that run least often and get tested least.
The two observed cases show this. In one, a server tried to send an error message on a socket that was blocked for writing, and the error path itself threw. In the other, Java code in a phone operating system hit an uncaught exception that put the device in a boot loop. A failure during startup is especially costly, since the program cannot recover on its own.
When you review code for this weakness, follow each thread and callback from its entry point to its outer edge and confirm that something at the top handles whatever escapes. Pay extra attention to error paths. Code that handles an error must not fail in turn.
Quick check
Is a global handler enough?
It is a safety net, not a plan. Catch expected failures near where they occur so the program can respond sensibly, and keep the global handler for the surprises.