VNX-1097: Persistent Storable Data Element without Associated Comparison Control Element
A class that defines an ordering without the matching equality: Java compareTo() without equals(Object), Kotlin compareTo() without equals(), Python __lt__/__le__/__gt__/__ge__ without __eq__.
| Field | Value |
|---|---|
| Rule ID | VNX-1097 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Java, Kotlin, Python |
| CWE | CWE-1097 |
| 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 | equality comparison reliability cwe-1097 |
| Source | internal/sast/rules/vnx-1097.rego |
Overview
VNX-1097 maps to CWE-1097: Persistent Storable Data Element without Associated Comparison Control Element. It reports a class whose comparison controls are incomplete: the class can be ordered, but equality was never defined to agree with that order.
Why This Matters
Sorted structures (TreeSet, TreeMap, bisect, sorted de-duplication) treat two objects that compare as 0 as the same element. ==, HashSet and dict keep using identity. The same pair of objects is then one entry in one collection and two in another, so lookups, de-duplication and stored copies disagree depending on which structure holds them. functools.total_ordering documents that the class must still supply __eq__.
Not reported: classes that also define equality, Java records and enums, Kotlin data classes, Python dataclasses and attrs classes, classes that extend another class (equality may be inherited), interfaces, and comments. The pairing of equals() with hashCode() is reported by VNX-581.
What Gets Flagged
public final class Version implements Comparable<Version> {
@Override
public int compareTo(Version other) { // FLAGGED: no equals(Object)
return Integer.compare(major, other.major);
}
}
@functools.total_ordering
class Money:
def __lt__(self, other): # FLAGGED: no __eq__
return self.cents < other.cents
Remediation
- Define
equals(andhashCode) or__eq__(and__hash__) over the same fields the ordering compares. - In Kotlin or Python, a data class or
@dataclass(order=True)generates both consistently. - For a confirmed false positive, add a
vulnetix-ignore: VNX-1097comment on the line.
References
- CWE-1097: Persistent Storable Data Element without Associated Comparison Control Element
- java.lang.Comparable: consistent with equals
- functools.total_ordering
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-1097
// nosec vnx-1097
Or record an ignore rule: vulnetix ignore add --rule vnx-1097 --reason "...". See Suppressing findings.