Safeguard
Application Security•

CWE-242 Use of Inherently Dangerous Function: gets() and Friends

Some C and C++ functions cannot be used safely however carefully you call them. CWE-242 covers gets(), banned function lists and how to enforce them.

Safeguard Security Team
5 min read

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.

  1. 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.
  2. 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.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.