Skip to content

VNX-597: String compared with == or != instead of equals()/strcmp()

Reports Java comparisons of a String with a string literal or with another String variable by == or !=, and C comparisons of a char pointer with a string literal, which compare references or addresses rather than content.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-597
Severity Medium
SARIF level warning
Kind sast
Languages Java, C
CWE CWE-597
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C
Tags java c string-comparison cwe-597
Source internal/sast/rules/vnx-597.rego

Overview

VNX-597 maps to CWE-597: Use of Wrong Operator in String Comparison. In Java, == on two Strings compares references, so the result depends on whether both happen to be the same interned object. In C, comparing a char * with a string literal compares addresses.

The rule reports:

  • in Java, any expression compared with a string literal by == or != (role == "admin", request.getParameter("a") == "x", also with the literal on the next line);
  • in Java, a comparison of two variables both declared String within the 60 lines above;
  • in .c files, an expression compared with a string literal.

It does not report equals, equalsIgnoreCase, Objects.equals or strcmp, comparisons with null, char literals (c == 'a'), C++ files (where std::string overloads ==), Kotlin (where == is equals), or operators inside comments and string literals. Boxed numbers and other objects compared by reference are VNX-595.

Why This Matters

A string read from a request, a file or a database is never the interned literal, so a check like if (role == "admin") is always false for real input and true only in a unit test that passes the literal. The reverse, if (token != expected), rejects or accepts depending on how the two values were built. Either way a security decision no longer depends on the value.

What Gets Flagged

if (role == "admin") { }                              // FLAGGED
if (request.getParameter("action") == "delete") { }   // FLAGGED
return presented == expectedToken;                    // FLAGGED (both String)
if (input == "letmein") { }                           /* FLAGGED */
// NOT FLAGGED
if ("admin".equals(role) || Objects.equals(role, "root")) { }
if (role == null || c == 'a') { }

Remediation

  1. Java: use "literal".equals(value) (null-safe) or Objects.equals(a, b); for secrets compare with MessageDigest.isEqual on the bytes.
  2. C: use strcmp/strncmp, or a constant-time comparison for secrets.

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

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

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