CWE-119, Improper Restriction of Operations within the Bounds of a Memory Buffer, is the parent of a whole family of memory bugs. The idea is simple. Your program has a block of memory with a start and an end, and it reads from or writes to a spot outside that block. What lives next to the buffer then gets touched: other variables, data structures, or internal program data.
MITRE lists the affected platforms as memory-unsafe languages: C, C++ and assembly. If you write Rust, Go, Java, Python or JavaScript, the language runtime normally checks bounds for you. That does not make you immune. Your Node runtime, your Python image library, your TLS stack and your router firmware are probably written in C or C++, and you inherit their bugs.
How it happens
A buffer is a fixed amount of space. A bug appears when the code does not respect that size. The usual causes are small and mundane.
- The code copies input into a buffer without checking how long the input is.
- An index comes from a packet, a file or a user and is never compared to the array length.
- A length field in a message says one thing while the real data says another.
- The size of the buffer was calculated wrongly, so it is smaller than the code assumes.
- A loop runs one step too far, or a counter goes the wrong way.
Because CWE-119 is a class, MITRE splits it into more specific children. Writing past the end is CWE-120 and its stack and heap variants. Reading past the end is CWE-125. Bad indexes are CWE-129. When you can, label a finding with the child, since the fix is clearer.
Here is the pattern at its simplest.
// Vulnerable: no check that name fits in buf
void greet(const char *name) {
char buf[16];
strcpy(buf, name);
printf("Hello %s\n", buf);
}
Any name of 16 bytes or more writes past the end of buf. The fix is to bound the copy and to handle truncation on purpose.
// Safer: the size is part of the operation
void greet(const char *name) {
char buf[16];
int n = snprintf(buf, sizeof buf, "%s", name);
if (n < 0 || (size_t)n >= sizeof buf) {
return; // reject or handle oversized input
}
printf("Hello %s\n", buf);
}
What an attacker gains
MITRE describes three outcomes, and the first is the one that makes this weakness famous.
Code execution and memory changes. If the attacker can control the memory they reach, they may run arbitrary code, as with a standard buffer overflow. If they can only overwrite a pointer's worth of memory, they may still be able to redirect execution.
Crashes and resource use. Out-of-bounds access very likely corrupts memory and possibly instructions, which often ends in a crash. MITRE also lists CPU and memory exhaustion as possible effects.
Information disclosure. An out-of-bounds read can expose sensitive data. If the data includes details such as where the buffer sits in memory, that knowledge helps craft further attacks.
The observed examples on the MITRE page show the range. CVE-2009-2550 is a classic stack-based overflow in a media player triggered by a long playlist entry. CVE-2020-29557 is a buffer overflow in a Wi-Fi router web interface, and CVE-2021-22991 is a buffer overflow caused by incorrect URI normalization in an application traffic product. MITRE notes both were exploited in the wild per CISA KEV.
How to find it
MITRE names four detection approaches for this class.
- Static analysis. Tools that use data flow or constraint-based techniques can often find the weakness in source code. They tend to miss issues that depend on the environment, so treat a clean report as partial evidence.
- Fuzzing and dynamic testing. Large test suites with many diverse inputs, including fuzz testing, stress testing and fault injection, exercise the code in ways a human would not think of.
- Compiler runtime checks. Build with AddressSanitizer (ASan) for C and C++. It inserts runtime checks for memory safety errors. MITRE rates this as moderately effective and notes that crafted inputs are still needed to reach the buggy code.
- Binary and bytecode analysis. When you do not have source, weakness analysis on binaries can give partial coverage at reasonable cost.
A practical setup is to run your unit tests and a fuzzer under ASan in CI. Crashes become failing builds instead of production incidents.
How to fix it
MITRE's record for this class does not list mitigations, since the fixes live in the child weaknesses. These steps follow from the descriptions above and from standard practice for memory-unsafe code.
- Pass the buffer size along with every pointer, and check it before any copy or index.
- Prefer bounded functions and safe containers, for example
snprintf,std::string,std::vectorandstd::span, over rawstrcpy,sprintfandgets. - Validate every length and index that comes from outside the program, including lengths inside file formats and network messages.
- Check size arithmetic before allocating. A wrong calculation produces a buffer that is smaller than the code expects.
- Use sanitizers and fuzzing as a standing part of the build, not a one-time audit.
- For new components, consider a memory-safe language where it fits.
Where dependencies come in
Most teams do not write the vulnerable code themselves. They ship it inside a library or a base image. Knowing which components you ship, and whether your code actually calls the vulnerable function, decides how urgent an advisory is. You can check a manifest for known issues with the free in-browser dependency scan. It needs no login, your file stays on your machine, and it covers up to 100 dependencies.
Click through it at your own pace, or open it full screen.
Quick check
Is CWE-119 only about writing past the end of a buffer?
No. It covers reads and writes, and locations before the start as well as after the end. Out-of-bounds reads can leak data, while writes can corrupt memory or enable code execution.
Do I need to worry if my application is written in Python or Java?
Your own code is bounds-checked by the runtime, but native libraries and the runtime itself are often written in C or C++. A vulnerable native dependency can expose you even when your code is memory safe.
What does AddressSanitizer do?
It is a compile-time option that adds runtime error checks for memory safety errors in C and C++. Run your tests and fuzzers with it enabled so out-of-bounds accesses stop the program with a clear report.