VNX-495: Private Data Structure Returned From A Public Method
A public Java method that returns an array type returns a private array field itself (return field; or return this.field;), so the caller receives a reference to the object's internal state and can change its elements. final on the field does not help: it fixes the reference, not the contents. Reported at the return statement. Not reported: a defensive copy (field.clone(), Arrays.copyOf, System.arraycopy into a new array, List.of/unmodifiableList), a private field initialised to an empty array (new T[0], {}), which cannot be changed, a local variable or method parameter that shadows the field, non-public methods, public fields (VNX-493 judges those), collections, and the pattern in comments or string literals.
| Field | Value |
|---|---|
| Rule ID | VNX-495 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Java |
| CWE | CWE-495 |
| 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 | private-array defensive-copy encapsulation cwe-495 |
| Source | internal/sast/rules/vnx-495.rego |
Overview
VNX-495 maps to CWE-495: Private Data Structure Returned From A Public Method. It reports public methods that hand out a private array field instead of a copy. VNX-375, the general mutable-return rule, leaves these lines to this rule and reports collections, dates and the other mutable fields.
Why This Matters
Arrays are mutable and returned by reference. A getter that returns roles lets the caller write getRoles()[0] = "admin" and change the object’s own state, bypassing every check the class performs on its setters. Marking the field final does not prevent this.
What Gets Flagged
public class KeyHolder {
private byte[] secretKey;
private final String[] roles;
public byte[] getSecretKey() {
return secretKey; // FLAGGED
}
public String[] getRoles() { return roles; } // FLAGGED
}
Not flagged: return secretKey.clone();, return Arrays.copyOf(roles, roles.length);, returning a private static final String[] EMPTY = new String[0];, and non-public methods.
Remediation
- Return a copy:
return secretKey.clone();orArrays.copyOf(...). - Return an unmodifiable view such as
List.of(roles)orCollections.unmodifiableList(...). - For secrets, avoid returning them at all; expose the operation (sign, verify) instead.
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-495
// nosec vnx-495
Or record an ignore rule: vulnetix ignore add --rule vnx-495 --reason "...". See Suppressing findings.