CWE-1069 describes an invokable code block that contains an exception handling block with no code in it. MITRE's wording covers catch and finally blocks. Any developer in a language with exceptions can write one, and most of us have, usually with the intention to come back later.
How it happens
The compiler demands that you handle a checked exception, or a failure seems harmless. The fastest way to silence the warning is an empty handler.
MITRE's example is a Java program dividing by zero and catching the ArithmeticException with nothing inside the block:
// Vulnerable pattern: the error vanishes and c keeps a stale value
public class Main {
public static void main(String[] args) {
int a = 1;
int b = 0;
int c = 0;
try {
c = a / b;
} catch (ArithmeticException ae) {
}
}
}
Nothing is logged and nothing is corrected. The program carries on as if the division worked.
The same shape appears in other languages:
# Vulnerable pattern: every failure is swallowed
try:
charge_card(order)
except Exception:
pass
Here the order may be treated as paid, shipped, or retried forever, and no one will know why.
What an attacker gains
MITRE lists reduced reliability: "When an exception handling block (such as a Catch and Finally block) is used, but that block is empty, this can prevent the product from running reliably. If the relevant code is reachable by an attacker, then this reliability problem might introduce a vulnerability."
Think about where this goes wrong in security code. A failed signature check, a failed permission lookup or a failed input validation that is swallowed leaves the program in whatever state it was in before. If that state is "allowed," the attacker is in. MITRE classes this weakness as indirect: a quality issue that can make security weaknesses easier to introduce or harder to detect.
How to find it
The record lists no detection methods, but this one is easy to check by hand and by tool:
- Search for
catchfollowed by an immediately closing brace, and forexceptfollowed bypass. - Turn on your linter's rule for empty blocks.
- During review, ask of every handler what the program does next and how an operator would know it happened.
A quick search that works in most repositories:
# Find Python handlers that only pass
grep -rn -A1 "except" --include=*.py . | grep "pass"
Try it yourself
A static code scan flags this kind of pattern automatically. This demo shows one in action.
Click through it at your own pace, or open it full screen.
How to fix it
MITRE's mitigation, for the Implementation phase: for every exception block, add code that handles the specific exception in the way intended by the application.
In practice:
- Catch the specific exception type, not a broad one.
- Decide what the correct behavior is: recover, retry, use a safe default, or stop.
- Log the event with enough detail to investigate.
- For security checks, fail closed. If you cannot confirm access, deny it.
MITRE's corrected Java version logs the error and sets a defined value:
catch (ArithmeticException ae) {
log.error("Divided by zero detected, setting to -1.");
c = -1;
}
If a handler truly has nothing to do, write a comment that says why, so the next reader knows it is deliberate.
Your dependencies can swallow errors too, but you cannot read all their code. The free scan at gold.safeguard.sh/scan lists known issues in your dependencies from a manifest file, with no login and up to 100 dependencies, and the file stays on your machine.
Quick check
What does MITRE recommend for every exception block?
Add code that handles the specific exception in the way the application intends.
Why is an empty handler worse around security checks?
If a check throws and the error is ignored, the code may continue as if the check passed, which can grant access it should deny.