VNX-914: Attribute name chosen by the request in setattr()
Reports Python setattr() whose attribute name comes from HTTP request data, so the client chooses which attribute it overwrites.
| Field | Value |
|---|---|
| Rule ID | VNX-914 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Python |
| CWE | CWE-914 |
| 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 | dynamic-attribute mass-assignment cwe-914 |
| Source | internal/sast/rules/vnx-914.rego |
Overview
setattr(obj, name, value) where the attribute name is Flask, Django or DRF request data, inline, through a variable assigned from it in the 15 lines above, or as the key of a for loop over a request mapping or its .items()/.keys(). The client picks the attribute: is_admin, password_hash, or a method it replaces.
Why This Matters
Any attribute of the object becomes writable from the request, including ones the form never showed, so a profile update can grant privileges or replace a bound method.
What Gets Flagged
setattr(user, request.form["field"], request.form["value"])
for key, value in request.get_json().items():
setattr(user, key, value)
Not flagged: a constant attribute name, a loop over a constant tuple, serializer validated_data or form cleaned_data, a loop that checks the key against an allow-list before the setattr, comments and strings. VNX-PY-016 and VNX-627 cover related shapes.
Remediation
Iterate an explicit allow-list of editable fields and read each from the request, or use a serializer or form that declares the fields.
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-914
// nosec vnx-914
Or record an ignore rule: vulnetix ignore add --rule vnx-914 --reason "...". See Suppressing findings.