CWE-1075 is code that performs an unconditional control transfer, such as a goto, outside a branching structure like a switch block. It shows up mostly in C and C++ and in older code, and it affects anyone who has to read that code later.
How it happens
A goto jumps to a label somewhere else in the function. One jump is easy to follow. Several, especially backward ones or ones that cross variable setup, turn the function into a puzzle.
/* Pattern to review: jumps that skip over code */
int process(Item *item) {
if (!item) goto fail;
if (!validate(item)) goto fail;
handle(item);
return 0;
fail:
log_error();
return -1;
}
Not every goto is wrong. Cleanup jumps like the one above are a common C idiom. The concern is jumps with no clear structure.
/* Clearer: structured flow with early returns */
int process(Item *item) {
if (!item || !validate(item)) {
log_error();
return -1;
}
handle(item);
return 0;
}
What an attacker gains
MITRE lists reduced maintainability and increased analytical complexity. The issue "indirectly affects security by making it more difficult or time-consuming to find and/or fix vulnerabilities" and "might make it easier to introduce vulnerabilities." A jump that skips an initialization or a check is the usual route.
How to find it
MITRE says automated static analysis (SAST) can find some instances by analyzing source code without running it. A plain search for goto gives a quick list to review.
grep -rn "goto " --include=*.c --include=*.cpp .
How to fix it
The record lists no mitigations, so these are general steps.
- Replace jumps with loops, early returns or helper functions.
- If you keep a cleanup label, keep it single, at the end, and jump only forward.
- Make sure no jump skips a variable initialization or a validation step.
- Add a lint rule to flag new gotos for review.
Quick check
Is every goto a weakness?
No. The concern is unstructured jumps that make the flow hard to follow. A single forward jump to a cleanup label is often acceptable, but each one deserves review.