CWE-1071 is source code that contains a block with no code in it. It applies to every language and every team. An empty block is often harmless, but it is also a reliable sign that something was left unfinished.
How it happens
MITRE explains that empty blocks can occur in the bodies of conditionals, function or method definitions, exception handlers and elsewhere. An empty block might be intentional, but it might indicate incomplete implementation, accidental code deletion, or unexpected macro expansion. For some languages and constructs the syntax allows an empty block, yet the missing behavior violates a convention or API.
Examples of how they appear:
# Pattern to review: a validation branch that does nothing
if not user.is_verified:
pass
// MITRE example: synchronizing on an object, then doing nothing inside
synchronized (this) {
}
MITRE notes this does not accomplish anything and may be a sign that a programmer is wrestling with synchronization but has not yet achieved the result they intend. The correct version places the code that accesses or modifies shared data inside the block.
The Java example from CWE-1069, an empty catch block after division by zero, is another form of the same pattern.
What an attacker gains
MITRE lists reduced reliability and nothing more specific. The risk is indirect. In the first example above, a check that was meant to reject unverified users does nothing, so the flow continues for everyone. A reviewer skimming the code sees the right condition and assumes the right behavior.
How to find it
MITRE says automated static analysis (SAST) can find some instances by analyzing source code without executing it. Do these as well:
- Turn on your linter's empty block rule.
- Search for
pass,{}bodies and emptyelsebranches. - Review any empty block in security checks first.
A quick search for Python:
grep -rn -B1 "^\s*pass\s*$" --include=*.py .
Try it yourself
This demo shows a static scan flagging patterns in source code.
Click through it at your own pace, or open it full screen.
How to fix it
The record lists no mitigations, so these steps are general practice.
- Decide what the block was meant to do. Check history, tickets and nearby code.
- If it was meant to act, implement it. For a security check, make the failure path deny the request.
- If it is truly intentional, add a comment that states why, so it does not look like an accident.
- If it is dead, delete it.
- Fail the build on new empty blocks outside a short allow list.
Take unfinished code seriously during release review. A stub that reached production is still code that runs.
You can also look beyond your own code. Safeguard offers a free in-browser dependency scan at gold.safeguard.sh/scan, with no login, up to 100 dependencies, and the file staying on your machine.
Quick check
Is every empty block a bug?
No. MITRE says an empty block might be intentional. It can also signal incomplete implementation, accidental deletion or unexpected macro expansion, so each one deserves a look.
What does an empty synchronized block do?
Nothing useful. It suggests the programmer meant to protect shared access but did not put the access inside the block.