Skip to content

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 "*".

Updated 02 Nov 2026Checked against cli@de9b52a
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") accepts evilexample.com;
  • a prefix check against a scheme and host with no trailing slash: url.startsWith("https://example.com") accepts https://example.com.evil.net;
  • a substring check for a domain: contains/includes/indexOf, Python in, 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$/ accepts evilacme.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

  1. Parse the URL and compare its host exactly against a set of allowed hosts.
  2. To allow subdomains, compare against "." + domain as well as the domain itself.
  3. Match a prefix only when it ends in /, and prefer parsed host comparison to prefixes.
  4. 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.

Edit this pageSources: cli/internal/sast/rules/vnx-183.rego, cli/internal/sast/docs/vnx-183.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.