Safeguard
Application Security•

CWE-595: Comparing Object References Instead of Contents

Using == on objects compares identity, not value, so equal objects look different. A classic Java bug that turns into a security bug when it guards a decision.

Safeguard Security Team
2 min read

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.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.