CWE-1164 is code that is not essential for execution. It makes no state changes and has no side effects that alter data or control flow, so removing it would have no effect on functionality or correctness. MITRE's extended description lists examples: dead code, initialization that is never used, empty blocks, and code that could be removed entirely by optimization.
MITRE classes it as a class level entry under CWE-710, improper adherence to coding standards. Usage is allowed with review, because a more specific child entry, such as the Struts unused validation form (CWE-107), may fit better.
How it happens
Code outlives its purpose. A feature is removed but its helper stays. A variable is initialized and never read. A refactor leaves an empty branch. A merge brings in a duplicated line. None of this breaks the build, so nobody is prompted to clean it up.
What an attacker gains
MITRE lists reduced reliability and reduced performance. There is no direct attacker benefit in the record.
The security relevance is that irrelevant code is often a symptom. MITRE lists CVE-2014-1266 as an observed example: an incorrect goto in Apple's SSL product bypassed certificate validation, enabling an adversary in the middle attack. In that bug, a stray duplicate jump meant the code after it was never reached. Unreachable code is exactly what dead code detection finds, so a tool flagging it may have pointed straight at the problem.
Dead code can also fool people. A reviewer reading a security check that can never run may believe it protects something. An unused function with a weak implementation can become reachable later by accident.
How to find it
MITRE notes static analysis can find some instances by building a model of the code without running it. Checks that work well:
- Enable compiler and linter warnings for unused variables, unreachable code and empty blocks.
- Run a static analysis pass that reports dead branches.
- Use code coverage from your tests and review long-uncovered code with suspicion, not just as a gap in tests.
- After any security fix, ask whether a check was added that can actually be reached.
How to fix it
The record lists no formal mitigations. Practical steps:
- Delete it. Version control keeps the history, so there is no need to comment code out.
- Investigate before deleting. Unreachable code in a security path may mean a control is broken. Find out why it is unreachable first.
- Make the warnings fail the build for unreachable code and unused values once the backlog is cleared.
- Remove unused dependencies too. Libraries that nothing calls are the dependency version of dead code, and reachability analysis can show which vulnerable functions your code never reaches.
/* Irrelevant code: the first assignment is never used */
int status = 0;
status = verify(cert);
if (status != 0) return status;
/* Cleaned up */
int status = verify(cert);
if (status != 0) return status;
Try it yourself
A code scan surfaces unreachable and unused code along with other findings. This demo walks through one.
Click through it at your own pace, or open it full screen.
Quick check
Why not just leave harmless dead code alone?
It can mislead reviewers, hide real bugs, and in the goto fail case the unreachable code signalled a broken security check.
What should you do before deleting unreachable code in a security path?
Find out why it is unreachable. The check may be broken, and deleting it would hide the evidence.