Skip to content

VNX-1023: Secret compared by prefix, suffix or truncation

Reports passwords, tokens, keys, signatures, digests, OTPs and PINs checked with startswith/endswith/regionMatches or compared after truncation in Python and Java, so an empty or short guess matches.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-1023
Severity Low
SARIF level note
Kind sast
Languages Java, Python
CWE CWE-1023
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:L/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L
Tags incomplete-comparison authentication cwe-1023
Source internal/sast/rules/vnx-1023.rego

Overview

VNX-1023 maps to CWE-1023: Incomplete Comparison with Missing Factors. It reports a secret (a name containing password, pwd, secret, token, key, signature, sig, digest, hmac, otp, pin or passcode) checked against another value by comparing only part of it:

  • X.startswith(Y) / endswith (Python) and X.startsWith(Y) / endsWith / regionMatches(...) (Java), where one side is a secret and the other a stored, expected or user-supplied value;
  • equality on truncated values: Python a[:n] == b and hmac.compare_digest(a[:n], ...), Java a.substring(0, n).equals(b) and a.equals(b.substring(0, n)).

Not reported: prefix checks against a string literal or a name that says it is a prefix, scheme or type (token.startswith("Bearer "), sig.startsWith(SIG_PREFIX)), tokenizer code, full-length comparisons, comments and string literals. Comparisons that omit a non-secret factor (a tenant or user id) are not statically recognisable and are not attempted.

Why This Matters

stored_key.startswith(provided) is true when provided is an empty string, and a truncated signature check can be brute-forced a few characters at a time. The comparison has dropped the factor that made it a secret check: the whole value.

What Gets Flagged

return stored_key.startswith(provided)
return submitted[:6] == expected_otp[:6]
return expectedToken.startsWith(supplied);
return computed.substring(0, 12).equals(signature);

Remediation

  1. Compare the full values in constant time: hmac.compare_digest(a, b) in Python, MessageDigest.isEqual(a, b) in Java.
  2. Reject empty or short input before comparing.

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

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

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