VNX-476: NULL Pointer Dereference
Detects a value that can be NULL being dereferenced before it is checked: an unchecked malloc/calloc/realloc/strdup/fopen/getenv result in C and C++, and an unchecked request parameter, header, environment variable, system property or listFiles() result in Java.
| Field | Value |
|---|---|
| Rule ID | VNX-476 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C, C++, Java |
| CWE | CWE-476 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | null-dereference cwe-476 |
| Source | internal/sast/rules/vnx-476.rego |
Overview
VNX-476 maps to CWE-476: NULL Pointer Dereference. Some calls return NULL as their normal way of saying “no”: an allocation that failed, a file that could not be opened, an environment variable or request parameter that was not sent. Dereferencing that result crashes the process, and on some platforms turns into memory corruption. The rule reports:
- C/C++: the result of
malloc,calloc,realloc,strdup,strndup,fopenorgetenvassigned to a variable and, within the next six code lines with no NULL test in between, dereferenced (p->f,p[i],*p) or passed to a libc function that dereferences it (memcpy,memset,strcpy,strlen,strcmp,sprintf,fgets,fprintf,fread,fclose,atoiand similar). - Java:
request.getParameter(...),request.getHeader(...),System.getenv(...)or one-argumentSystem.getProperty(...)dereferenced by a chained call, or assigned to a variable whose method is called within six code lines without a null check, and a for-each overFile.listFiles().
Not reported: an allocation made inside an if/while condition, a variable tested before use (== NULL, !p, p &&, assert, serverAssert, a ternary, Objects.requireNonNull, Assert.notNull, StringUtils.isEmpty), wrapper allocators such as xmalloc/zmalloc that never return NULL, a constant-first comparison ("x".equals(v)), getProperty with a default, the system properties the JVM always defines (os.name, user.home, user.dir, java.*, the separators), and comments. NULL returned by the project’s own functions, fields and cross-function flows are not followed.
What Gets Flagged
// FLAGGED: malloc may return NULL
char *out = (char *) malloc(len + 1);
memcpy(out, msg, len);
// FLAGGED: HOME may be unset
const char *home = getenv("HOME");
strcpy(dst, home);
// FLAGGED: null when the parameter is absent
String q = request.getParameter("q").trim();
String auth = req.getHeader("Authorization");
if (auth.startsWith(scheme)) { ... }
What Is Not Flagged
char *p = malloc(len + 1);
if (p == NULL)
return NULL;
memcpy(p, name, len);
String name = request.getParameter("name");
if (name == null) return "anonymous";
return name.trim();
Remediation
- Check every allocation,
fopenandgetenvresult before using it, and handle the failure (return an error, use a default). - In Java, test request values and environment variables for null, use
Optional.ofNullable, or callgetProperty(key, default). - Put the constant first in comparisons (
"debug".equals(mode)) so a null value compares false instead of throwing.
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-476
// nosec vnx-476
Or record an ignore rule: vulnetix ignore add --rule vnx-476 --reason "...". See Suppressing findings.