VNX-183: Permissive List of Allowed Inputs
Reports allow-list checks on a URL, host, origin or redirect target that accept more than they name (a domain suffix without a leading dot, a host prefix without a trailing slash, a substring match, url.includes(allowedUrl), an unanchored or unescaped domain regex) and allow-lists whose entry is the wildcard "*".
| Field | Value |
|---|---|
| Rule ID | VNX-183 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Java, JavaScript / TypeScript, Python, Go, PHP |
| CWE | CWE-183 |
| 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 | allowlist validation open-redirect cors cwe-183 |
| Source | internal/sast/rules/vnx-183.rego |
Overview
VNX-183 maps to CWE-183: Permissive List of Allowed Inputs. It reports, in Java, JavaScript/TypeScript, Python, Go and PHP:
- a suffix check against a domain with no leading dot:
origin.endsWith("example.com")acceptsevilexample.com; - a prefix check against a scheme and host with no trailing slash:
url.startsWith("https://example.com")acceptshttps://example.com.evil.net; - a substring check for a domain:
contains/includes/indexOf, Pythonin,strings.Contains,strpos/str_contains; - any of these against an allow-list entry held in a variable named
allowed…/trusted…/whitelist…/safe…(url.includes(allowedUrl)in a loop over the allow-list); - a regular-expression allow-list (
/.../.test(origin),origin.match(/.../),re.match/re.search) for a domain with an unescaped., no$and no/after the host, no start anchor, or a wildcard before the domain:/acme\.com$/acceptsevilacme.com; - an allow-list variable (
ALLOWED_HOSTS,CSRF_TRUSTED_ORIGINS,allowedOrigins…) whose entry is"*".
The checked value can be a parsed host or a header getter (URI.create(u).getHost(), urlparse(u).netloc, req.get('origin'), r.Header.Get("Referer"), $_SERVER['HTTP_REFERER']) or a local derived from a URL-named value in one or two assignments. A check on a value named origin, referer, redirect… or callback… is always a trust decision. A value named url or host is treated as one when a redirect, a CORS header or a trusted/allowed/internal name appears within six lines.
Not reported: exact equality and set membership (ALLOWED.contains(origin), host in ALLOWED_HOSTS), a suffix with a leading dot (.endsWith(".example.com")), a prefix ending in /, a regex anchored at both ends with escaped dots (or ending the host with (?:\/|$)), re.fullmatch, checks on values (email addresses, file names) not named as a URL, host or origin, scheme-only and path prefixes ("https://", "/api/"), bundled third-party code, comments and string literals.
Why This Matters
An allow-list is only as narrow as its comparison. A suffix or substring check on a host lets an attacker register a domain that contains yours and pass an open-redirect, CORS or SSO-callback check; a wildcard entry turns the list off altogether.
What Gets Flagged
// FLAGGED
if (url.startsWith("https://example.com")) { return "redirect:" + url; }
return origin.endsWith("example.com");
// FLAGGED
for (const allowedUrl of redirectAllowlist) {
allowed = allowed || url.includes(allowedUrl)
}
// FLAGGED: no start anchor
return /acme\.com$/.test(origin);
# FLAGGED
ALLOWED_HOSTS = ['*']
if urlparse(target).netloc.endswith("acme.com"): ...
# NOT FLAGGED: exact host, or a dot boundary
return hostname == "acme.com" or hostname.endswith(".acme.com")
Remediation
- Parse the URL and compare its host exactly against a set of allowed hosts.
- To allow subdomains, compare against
"." + domainas well as the domain itself. - Match a prefix only when it ends in
/, and prefer parsed host comparison to prefixes. - List the hosts or origins that are allowed instead of
*.
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-183
// nosec vnx-183
Or record an ignore rule: vulnetix ignore add --rule vnx-183 --reason "...". See Suppressing findings.