CWE-595 is the mistake of comparing object references when you meant to compare their contents. The code then fails to detect objects that are equivalent.
MITRE's example is Java, where using == on objects usually gives deceptive results because the operator compares references. The same family of errors is listed for JavaScript and PHP too.
How it happens
Two strings can hold the same characters and still be two separate objects.
// Vulnerable pattern
String role = request.getParameter("role"); // "admin" built at runtime
if (role == "admin") {
grantAdminTools(); // usually never runs, or runs only by accident
}
Sometimes the comparison appears to work, because the language reuses one object for identical literals. That is what makes it dangerous: tests pass on literals, then production data comes from parsing, a database, or the network, and behaviour changes.
What an attacker gains
The record lists the impact as erroneous results that can cause unexpected application behaviour, varying by context. When the comparison guards a decision, such as a role check, a token match, or an allow list lookup, the wrong answer becomes a security flaw. A check that always fails might lock out legitimate users. A check inverted with != might let the wrong ones in.
How to find it
Static analysis (SAST) can find some instances by recognising reference comparison on types that should be compared by value. Code review should treat every == between non-primitive values as a question.
How to fix it
MITRE's guidance for Java: use the equals() method to compare objects instead of the == operator. If you do rely on ==, it matters for performance that your objects are created by a static factory, not by a constructor.
if ("admin".equals(role)) { // literal first also avoids a null pointer
grantAdminTools();
}
For secrets and tokens, use a constant-time comparison such as MessageDigest.isEqual on the byte arrays, so you fix correctness and timing at once.
Quick check
Why can == seem to work in tests?
Identical string literals may share one object, so references match. Strings built at runtime are separate objects and do not.