Skip to content

VNX-290: Authentication Bypass by Spoofing

Detects trust decisions on a client IP taken from a client-controlled header (X-Forwarded-For, X-Real-IP, True-Client-IP, HTTP_X_FORWARDED_FOR): comparison with an IP literal, allow-list membership, an is_trusted-style helper, an address-class test (is_private, isLoopbackAddress), or a rate limiter keyed on the header.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-290
Severity High
SARIF level error
Kind sast
Languages Java, JavaScript / TypeScript, Python
CWE CWE-290
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:H/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:H/DI:H/EX:H/EC:N/P:H
Tags auth spoofing x-forwarded-for cwe-290
Source internal/sast/rules/vnx-290.rego

Overview

VNX-290 maps to CWE-290: Authentication Bypass by Spoofing. X-Forwarded-For and its relatives are request headers: the client writes them. Code that grants access when the header says 127.0.0.1, or limits login attempts per header value, can be bypassed by sending a different value.

The rule reports the header value (read inline, or through a variable assigned from it, or derived from such a variable such as xff.split(',')[0], in the 12 lines above) when it is:

  • compared with an IP or localhost literal (==, ===, !=, .equals, .startsWith),
  • tested for membership (in ALLOWED, .includes, .contains, .has, .indexOf) or passed to an is_trusted/isInternal/isAllowed-style helper,
  • or used as a rate-limiter key (keyGenerator, key_func, keyResolver).

What Gets Flagged

x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
    ip = x_forwarded_for.split(',')[0]
if ip == '127.0.0.1':          # FLAGGED
    return HttpResponse(render_status())
String clientIp = request.getHeader("X-Forwarded-For");
if ("127.0.0.1".equals(clientIp)) {   // FLAGGED
keyGenerator ({ headers, ip }) { return headers['X-Forwarded-For'] ?? ip }   // FLAGGED

What Is Not Flagged

  • Logging or storing the header, and null or empty checks.
  • Decisions on the socket address (request.getRemoteAddr(), REMOTE_ADDR, Express req.ip with trust proxy).
  • Setting the header on a response or outgoing request, test code and comments.

Whether a trusted reverse proxy overwrites the header before it reaches this code is deployment configuration and is not judged.

Remediation

Use the socket address, or let the framework take the client address from a known number of trusted proxies (Express app.set('trust proxy', 1), Werkzeug ProxyFix(x_for=1), Spring ForwardedHeaderFilter). Authenticate callers rather than trusting their address, and key rate limits on the socket address or the targeted account.

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-290
// nosec vnx-290

Or record an ignore rule: vulnetix ignore add --rule vnx-290 --reason "...". See Suppressing findings.

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