VNX-1043: Data Element Aggregating an Excessively Large Number of Non-Primitive Elements
Reports a Java class, Go struct, Python class or TypeScript class/interface that declares more than 10 instance fields of non-primitive type, on its declaration line.
| Field | Value |
|---|---|
| Rule ID | VNX-1043 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Java, Python, JavaScript / TypeScript, Go |
| CWE | CWE-1043 |
| CAPEC | CAPEC-130 |
| 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 | data-aggregation excessive-fields code-quality cwe-1043 |
| Source | internal/sast/rules/vnx-cwe1043-auto.rego |
Overview
VNX-1043 applies the CISQ maintainability measure behind CWE-1043: a data element that aggregates too many other objects. It counts the instance fields declared directly in the body of each type and reports the declaration when more than 10 of them are of a non-primitive type.
What is counted:
- Java: instance fields of a
class(notstaticfields, constants or records). - Go: fields of a
structtype, including grouped names (a, b *T) and embedded types. - Python: annotated class-level fields (dataclasses, pydantic, attrs or any class), not
ClassVar. - TypeScript: fields of a
class, aninterfaceor an objecttypealias.
A field is non-primitive when its type names anything other than a primitive or value type: numbers, booleans, strings, bytes, dates, times, durations, UUIDs, BigDecimal, the boxed types, error and any/unknown. So List<Order>, map[string]*Session, Optional[Cart] and Role[] count, while List<String>, []byte, dict[str, str] and 'light' | 'dark' do not.
Not reported: fields of a nested class (they count toward the nested class), method parameters, enums, plain JavaScript, generated code (Code generated ... DO NOT EDIT, @Generated), test code and comments. CISQ suggests 5 as the threshold; this rule uses 10 so that it reports only the outliers.
Why This Matters
An object that holds a dozen other objects is hard to review. Each one is something it might serialise into a response, write to a log, keep alive in a cache or hand to another component. When a type grows to that size, nobody checks every field before the type is returned from an API, and data that was never meant to leave the server leaves with it.
What Gets Flagged
public class OrderContext { // FLAGGED: 12 non-primitive fields
private final Customer customer;
private Address billingAddress;
private List<OrderLine> lines;
private Map<String, Discount> discounts;
// ... eight more object fields
}
type Server struct { // FLAGGED
cfg *Config
sessions map[string]*Session
inbound, outbound chan *Message
*Logger
// ...
}
What Is Not Flagged
public class Customer {
private Long id;
private String email; // strings, boxed numbers and dates are primitive here
private Address address;
}
Remediation
- Group related fields into their own types (an
Addressesvalue with billing and shipping, aPaymentwith method and invoice). - Keep request-scoped context separate from long-lived dependencies.
- Return purpose-built response types from APIs instead of the aggregate itself.
References
- CWE-1043: Data Element Aggregating an Excessively Large Number of Non-Primitive Elements
- CISQ Automated Source Code Maintainability Measure
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-1043
// nosec vnx-1043
Or record an ignore rule: vulnetix ignore add --rule vnx-1043 --reason "...". See Suppressing findings.