CWE-242 is a short definition with a long reach: the product calls a function that can never be guaranteed to work safely. MITRE lists the platforms as C and C++.
Most unsafe code is unsafe because of how a function is called. This entry is different. For these functions, there is no safe way to call them. The problem is in the function itself.
How it happens
MITRE explains that certain functions behave in dangerous ways regardless of how they are used, and that functions in this category were often implemented without taking security concerns into account.
The standard example is gets(). It reads from standard input into a buffer and performs no bounds checking on the size of its input. The caller has no way to tell it how big the buffer is. An attacker can send input of any length, and the destination buffer overflows.
MITRE adds a second example from C++: the stream extraction operator, used to read into a statically allocated character array, is unsafe for the same reason. It does not bound the amount it writes, so arbitrarily sized input overflows the array.
Here is the vulnerable pattern, based on MITRE's own demonstrative example:
/* Vulnerable: gets() cannot be told how large buf is */
char buf[24];
printf("Please enter your name and press Enter\n");
gets(buf);
And a corrected version that bounds the read:
/* Fixed: fgets() takes the buffer size */
char buf[24];
printf("Please enter your name and press Enter\n");
if (fgets(buf, sizeof(buf), stdin) == NULL) {
/* handle end of file or read error */
return 1;
}
buf[strcspn(buf, "\n")] = '\0'; /* strip the newline if present */
Note the check of the return value. fgets() returns NULL on error or end of file, and ignoring that brings in a different weakness, covered in our post on CWE-252.
What an attacker gains
The record lists the consequence as "Other: varies by context". That is honest: the entry names a risky practice, not one outcome. In real code the usual result of an unbounded read is a buffer overflow, and what follows depends on the program and where it runs.
MITRE's observed example is CVE-2007-4004. An FTP client used the inherently insecure gets() function and was setuid root on some systems, allowing a buffer overflow. The setuid detail matters: it turned a bug in a client into a potential route to root. That overlap with excess privilege is covered in our post on CWE-250.
How to find it
This is one of the easier weaknesses to find, because the pattern is a function name.
MITRE lists automated static analysis, which it rates high effectiveness for this entry. Static analysis builds a model of data flow and control flow, then looks for risky patterns connecting sources of input to sinks. For a banned function, even a simple match is enough.
The record's testing guidance is plainer still: use grep or static analysis tools to spot usage of dangerous functions.
grep -rn --include='*.c' --include='*.cpp' -E '\bgets\s*\(' src/
The same search should cover third party code you vendor into your tree, not just your own files.
How to fix it
MITRE gives two mitigations.
- In the Build and Compilation and Implementation phases, identify a list of prohibited API functions and prohibit developers from using them, while providing safer alternatives. In some cases code analysis tools or the compiler can be told to spot prohibited functions, for example the "banned.h" include file from Microsoft's SDL.
- In Testing, use grep or static analysis tools to spot usage of dangerous functions.
In practice, that adds up to a short program:
- Write the banned list down. Start with gets() and the unbounded stream read into fixed arrays.
- Name the replacement for each entry so developers are not left guessing.
- Enforce it in the build or in CI so a banned call fails the pipeline.
- Review the banned list when you adopt a new library or language standard.
A rule that lives only in a wiki gets forgotten. A rule that fails a build does not.
Banned lists in a team setting
A banned function list works best when it is short, specific and automatic. Long lists get ignored. Short ones that fail a build get followed.
Treat each addition as a small design decision. Name the function, say why it is unsafe, and give the replacement that people should use. A developer who hits a build error with a clear fix will move on. One who hits a build error with no guidance will look for a way around it.
Remember that the weakness is about the function, not the author. A careful, experienced developer calling gets() still produces an overflow, since the function offers no way to be careful. That is why a rule beats advice here.
Try it yourself
Run a code scan over a small sample and see how a banned function call is flagged.
Click through it at your own pace, or open it full screen.
Quick check
Why can gets() never be made safe?
It has no parameter for the buffer size, so it cannot limit how much it writes. Any caller is exposed to input longer than the buffer.
What is the first step MITRE recommends?
Identify a list of prohibited API functions, prohibit developers from using them, and provide safer alternatives. A compiler or analysis tool can help enforce it.
Does the entry apply to languages other than C and C++?
MITRE lists C and C++ as the platforms for this entry.