Skip to content

VNX-836: Use of Password Hash Instead of Password for Authentication

Detects pass-the-hash authentication: a stored password hash compared directly with a value from the request, without hashing a password on the server. Python, Java and JavaScript/TypeScript.

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

Overview

VNX-836 maps to CWE-836: Use of Password Hash Instead of Password for Authentication. When a login endpoint accepts a hash from the client and compares it with the stored hash, the hash is the password. Anyone who reads the user table (a SQL injection, a leaked backup) can log in as every user without cracking anything.

The rule reports a comparison (==, !=, ===, .equals(), compare_digest(), MessageDigest.isEqual(), crypto.timingSafeEqual()) between a stored-hash field or getter (password_hash, passwordHash, hashed_password, pwd_hash, getPasswordHash()) and a request value: request.form/args/json/POST/GET, request.getParameter/getHeader, req.body/query/params/headers, a variable assigned from one within the ten lines above, or a Spring @RequestParam/@RequestHeader String parameter.

What Gets Flagged

if user is None or user.password_hash != request.form["password_hash"]:   # FLAGGED
    abort(401)
if (!user || user.passwordHash !== req.body.passwordHash) {   // FLAGGED
  return res.status(401).end();
}
if (user.getPasswordHash().equals(request.getParameter("hash"))) {   // FLAGGED

What Is Not Flagged

  • The request password hashed on the server before the comparison (hashlib, pbkdf2_hmac, bcrypt, hash_password() and similar).
  • bcrypt.compare(req.body.password, user.passwordHash), check_password_hash(...) and other verify functions.
  • Comparisons of two stored hashes, and the pattern in comments or string literals.

Remediation

Accept the password itself over TLS and verify it on the server with a password hashing function (bcrypt, scrypt, Argon2, PBKDF2) and its verify call. If the client must not send the password, use a challenge-response or token protocol rather than a static hash.

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

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

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