CWE-617, Reachable Assertion, covers an assert() or similar statement that an attacker can trigger, causing an exit or other behavior more severe than necessary. It applies in C, Java, Rust and other languages.
How it happens
Assertions catch logic errors. They are meant for conditions that should never happen. The weakness appears when outside input can make the "impossible" condition true.
MITRE's example is a server handling many simultaneous connections. If an assertion in one connection's handling aborts the whole process, every other connection drops too. The assertion's scope reaches beyond the attacker's own session.
// Vulnerable: input decides whether the process lives
void handle(struct req *r) {
assert(r->len > 0); // attacker sends an empty request
process(r);
}
// Fixed: reject the bad request, keep the server running
void handle(struct req *r) {
if (r->len == 0) { send_error(r, 400); return; }
process(r);
}
The record lists several real cases: an API server for an LLM library that could crash on an empty prompt (CVE-2024-8768), an FTP server that aborted on crafted commands, and a chat client that crashed on a long message. One entry is a chain where a web caching proxy function did not check a return value correctly, leading to a reachable assertion.
What an attacker gains
Availability impact: DoS through crash, exit or restart. MITRE stresses that this holds if the relevant code can be triggered by an attacker and the assert's scope extends beyond the attacker's own session.
How to find it
Static analysis (SAST) can find some instances by analyzing source or compiled code. Review each assert and ask whether any input, however unusual, can reach it. Fuzzing with empty, oversized and malformed input also surfaces them quickly.
How to fix it
From MITRE:
- Keep sensitive open or close operations non reachable by directly user-controlled data.
- Validate user data before it reaches the assertion.
Also decide per call whether the condition is an internal invariant (assert is fine) or a property of input (return an error).
If the crash lives in a library you depend on, reachability analysis tells you whether your code actually calls the affected function, which helps you decide how fast to upgrade.
A closer look at scope
The difference between a harmless assertion and a vulnerable one is scope. In a single-user command line tool, an assertion that stops the program only hurts the person who triggered it. In a server, the same assertion may stop every user's work.
That is why MITRE ties the impact to two conditions: the attacker can reach the code, and the assert reaches beyond the attacker's own session. Both conditions are worth checking for each assertion in network-facing code.
The record's list of examples spans very different software: an FTP daemon, a chat client, a caching proxy and an LLM library server. The common thread is input that the author did not expect, such as an empty prompt or an oversized string. Think about the shortest and longest inputs your code can receive, and about values like zero and null, then see which assertions they trip.
Some teams compile assertions out of release builds. That changes the behavior but does not remove the question. If the check was guarding something real, removing it may open a different weakness, so replace it with explicit error handling instead.
Quick check
Is every assert a vulnerability?
No. It becomes one when an attacker can trigger it and the result is worse than needed, such as stopping a server for all users.