VNX-184: Incomplete List of Disallowed Inputs
Reports input validation by deny-list: a collection of attack tokens (shell metacharacters, <script/javascript:, ../, SQL comment and keyword tokens, executable extensions) that is named as a deny-list or applied to input with contains/replace/in.
| Field | Value |
|---|---|
| Rule ID | VNX-184 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Go, Java, JavaScript / TypeScript, Python, PHP |
| CWE | CWE-184 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | denylist validation cwe-184 |
| Source | internal/sast/rules/vnx-184.rego |
Overview
VNX-184 maps to CWE-184: Incomplete List of Disallowed Inputs. It reports a collection literal (Python list/tuple/set/dict, JavaScript array, Java List.of/Arrays.asList/Set.of, Go slice or map, PHP array(...)) whose entries are attack tokens, when either:
- the variable is named as a deny-list (
blacklist,denylist,blocklist,forbidden…,disallowed…,banned…,blocked…,dangerous…,unsafe…,bad…,…filter) and holds at least one such token; or - it holds two or more tokens of one family and the file applies it within 40 lines (
contains,includes,replace,str_replace(array_keys(...)),in, afor/rangeloop).
The families are shell metacharacters (; && | || & ` $( > <), script and HTML (<script, javascript:, onerror, onload, <iframe), traversal (../, ..\, /etc/passwd) and SQL (--, /*, ', union, select, drop…, with at least one comment, quote or union token). Executable extensions (.php, .exe, .jsp, .sh…) count for a deny-named list.
Not reported: escaping tables (entries mapped to a non-empty replacement), allow-lists, deny-named lists of other values (IP addresses, user names), token lists the file never applies, test files, comments and string literals.
Why This Matters
A deny-list is a guess at every dangerous input. Removing ; and && leaves |, ||, a newline and $(...); rejecting <script leaves <img onerror=...>; rejecting .php leaves .phtml and .PHP. The attacker only needs the one the list forgot.
What Gets Flagged
// FLAGGED: removing two shell separators before shell_exec
$substitutions = array(
'&&' => '',
';' => '',
);
$target = str_replace(array_keys($substitutions), $substitutions, $target);
// FLAGGED
private static final List<String> DENY_LIST = List.of(";", "&&", "|");
// FLAGGED
var forbiddenExtensions = []string{".php", ".exe", ".sh"}
# NOT FLAGGED: an escaping table and an IP block-list
HTML_ESCAPES = {"&": "&", "<": "<", ">": ">"}
BLOCKED_IPS = ["10.0.0.1"]
Remediation
- Validate against an allow-list of what is permitted (a host-name pattern, a set of extensions, an enum of values).
- Better still, use the API that removes the need to filter: an argument array instead of a shell string, a parameterised query, context-aware output encoding.
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-184
// nosec vnx-184
Or record an ignore rule: vulnetix ignore add --rule vnx-184 --reason "...". See Suppressing findings.