CWE-1285 is about input that is expected to specify an index, position or offset into an indexable resource such as a buffer or file, where the product does not validate it or validates it wrongly. It applies in any language, and it is a common root of memory safety bugs in C and C++.
How it happens
Memory buffers and files can be accessed with an index, such as an array position, or an offset, such as a position in a file. When untrusted input supplies that value and the code uses it unchecked, an attacker can reach portions of the resource that were never meant to be accessible.
MITRE says this can cause buffer overflows, excessive resource allocation or unexpected failures.
Two recorded cases are old, and still easy to recognize.
- CVE-2005-0369: a large ID in a packet was used as an array index.
- CVE-2001-1009: a negative array index was passed as an argument to the POP LIST command.
One was too large, the other too small. A check for only one side of the range is a half check.
Vulnerable and fixed
/* Vulnerable: idx comes from the packet */
int get_item(int *table, int idx) {
return table[idx];
}
/* Safer: check both bounds against the real size */
int get_item(const int *table, size_t table_len, long idx, int *out) {
if (idx < 0 || (size_t)idx >= table_len) {
return -1;
}
*out = table[idx];
return 0;
}
In memory safe languages the failure is usually an exception, but the same bug can still cause denial of service or read the wrong record.
# Vulnerable to wrong data: negative index wraps from the end
def get_record(records, i):
return records[i]
# Safer: reject out of range, including negatives
def get_record(records, i):
if not (0 <= i < len(records)):
raise IndexError("index out of range")
return records[i]
The Python example matters because a negative index does not crash. It silently returns the last item, which can leak or expose the wrong record.
File offsets work the same way:
# Safer: validate offset and length against the file size
import os
def read_at(path, offset, length):
size = os.path.getsize(path)
if offset < 0 or length < 0 or offset + length > size:
raise ValueError("bad offset or length")
with open(path, "rb") as f:
f.seek(offset)
return f.read(length)
What an attacker gains
The record tags the consequences as varying by context. Following the description, the outcomes are access to unauthorized parts of a resource, buffer overflows, resource exhaustion and crashes. In memory unsafe code an out of bounds read or write can progress to information disclosure or code execution.
How to find it
MITRE notes that automated static analysis (SAST) can find some instances by modeling data flow in source or compiled code. You can add:
- A search for every array access, slice or seek whose index traces back to request data, a packet field or a file header.
- Boundary tests with minus one, zero, the length, the length plus one, and the largest integer.
- Fuzzing of protocol and file parsers.
- Compiler and runtime checks such as bounds checking builds in test environments.
How to fix it
The record lists no mitigation text. These steps follow from the weakness.
- Check every externally supplied index against the real size of the resource, on both ends of the range.
- Use unsigned or checked types carefully, since signed to unsigned conversion can turn a negative number into a huge positive one.
- Prefer APIs that carry the length with the data, so the check cannot drift away from the buffer.
- Choose memory safe languages or safe containers for new parsing code where you can.
- Fail closed. On an invalid index, reject the request instead of clamping silently.
Dependencies matter here too. Parsers in libraries have this bug class often, and your code inherits it. The free in-browser dependency scan checks a manifest of up to 100 dependencies without a login, and the file stays on your machine.
Quick check
Why test negative indexes in a language that raises exceptions?
Some languages treat a negative index as counting from the end, so it returns real data instead of failing. That can expose the wrong record.
What two ends of the range should a check cover?
The lower bound, so no negative values, and the upper bound, so nothing at or beyond the length of the resource.