VNX-394: Unexpected Status Code or Return Value
Python code uses an HTTP response body (requests, httpx, a session) without checking its status, or slices a string at str.find()/rfind() without checking for -1.
| Field | Value |
|---|---|
| Rule ID | VNX-394 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Python |
| CWE | CWE-394 |
| 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 | status-code cwe-394 |
| Source | internal/sast/rules/vnx-394.rego |
Overview
VNX-394 maps to CWE-394: Unexpected Status Code or Return Value. It reports two concrete shapes in Python:
- The body of a response from
requests,httpxor a requests session (.get/.post/.put/.patch/.delete/.head/.request) read with.json(),.textor.content, either chained on the call or from the variable it was assigned to within the next 12 lines, with noraise_for_status(),status_code,.okor.statuscheck and no test of the response in between. - A slice indexed directly by
find()/rfind()of the same string (s[s.find(":") + 1:],s[:s.find("-")]), which returns the wrong text when the substring is absent (-1).
Not reported: a checked response, a module whose session installs a raise_for_status response hook, s[s.rfind("/") + 1:] (the after-last-separator idiom, which is correct when rfind returns -1), a cache or dict .get(), soup.find(), a find() result tested before use or guarded by an in test just above, test files, comments and docstrings.
Why This Matters
An HTTP client returns 4xx and 5xx responses as ordinary values. Code that parses them as success processes an error page as data, crashes with a confusing decode error, or stores an error message as if it were the record.
What Gets Flagged
r = requests.get(url, headers=headers)
return [repo["name"] for repo in r.json()] # FLAGGED
return requests.post(url, json=payload).json()["embedding"] # FLAGGED
return line[line.find(":") + 1:].strip() # FLAGGED
Remediation
- Call
response.raise_for_status()(or checkresponse.ok/status_code) before reading the body. - Check
find()for -1, or usestr.partition()orstr.index(), which make the missing case 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-394
// nosec vnx-394
Or record an ignore rule: vulnetix ignore add --rule vnx-394 --reason "...". See Suppressing findings.