VNX-909: Missing Initialization of Resource
A Java private object field that nothing in its class assigns and no framework annotation fills is dereferenced, so its first use throws NullPointerException.
| Field | Value |
|---|---|
| Rule ID | VNX-909 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Java |
| CWE | CWE-909 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L |
| Tags | missing-initialization-of-resource cwe-909 null-pointer |
| Source | internal/sast/rules/vnx-909.rego |
Overview
VNX-909 maps to CWE-909: Missing Initialization of Resource. It reports, on the declaration, a Java private field holding an object (a DataSource, Cipher, Map, lock, array …) that nothing in its class ever assigns, while the class dereferences it: dataSource.getConnection(), this.cipher.doFinal(...), cache.get(id), allowed.length, synchronized (lock), for (X x : listeners).
The field must be private, not final, not primitive, without an initializer and without an annotation (@Autowired, @Inject, @Mock, @Value, @BindView …), and the file must contain no assignment to it (name = ..., this.name = ..., in a constructor, setter, initializer block or a lazy if (x == null) x = ...).
Not reported: classes whose fields a framework or Lombok fills (@Data, @Setter, @Builder, @AllArgsConstructor, @Value, @Entity, @Embeddable, @Document, @XmlRootElement), files that use reflection (setAccessible(true)), fields shadowed by a parameter, lambda or loop variable of the same name (unless dereferenced through this.), primitives, final fields (the compiler enforces their initialization), test sources, comments and strings. A field set by an unannotated serializer (plain Gson) is invisible to the rule.
Why This Matters
A service whose data source, cipher or lock is never set compiles and starts, then fails with NullPointerException on the first request that reaches it. Depending on where the exception is caught, that is a denial of service, a security control that silently does nothing (an encryption step that is skipped), or a stack trace returned to the caller.
What Gets Flagged
public class ReportService {
private DataSource dataSource; // FLAGGED
private Cipher cipher; // FLAGGED
public int count() throws SQLException {
try (Connection c = dataSource.getConnection()) { ... }
}
public byte[] seal(byte[] data) throws Exception {
return this.cipher.doFinal(data);
}
}
private Object lock; // FLAGGED: synchronized (lock)
Not flagged: @Autowired private UserRepository users;, a field set by this.repo = repo; in the constructor, if (cache == null) cache = new HashMap<>();, private int count;, fields of an @Entity or a Lombok @Setter class.
Remediation
- Initialize the field at its declaration or in every constructor, and make it
finalwhen it never changes. - Use constructor injection rather than leaving a field for something else to set.
- If a field is filled by a framework, annotate it so the dependency is explicit.
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-909
// nosec vnx-909
Or record an ignore rule: vulnetix ignore add --rule vnx-909 --reason "...". See Suppressing findings.