Skip to content

VNX-257: Storing Passwords in a Recoverable Format

Reports a password passed as the data of a reversible transform (base64, hex, rot13, Fernet/AES/cipher encryption, CryptoJS, openssl_encrypt, AEAD Seal) and any decrypt_password/decryptPassword function.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-257
Severity High
SARIF level error
Kind sast
Languages Go, Java, JavaScript / TypeScript, PHP, Python, Ruby
CWE CWE-257
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:H/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:H/DI:H/EX:H/EC:N/P:H
Tags password-recovery reversible cwe-257
Source internal/sast/rules/vnx-257.rego

Overview

An encoded or encrypted password can be turned back into the password by anyone holding the stored value, or the stored value and the key. Passwords should be hashed with a slow, salted function, and forgotten passwords reset rather than recovered. This maps to CWE-257: Storing Passwords in a Recoverable Format.

What Gets Flagged

The first (data) argument of a reversible transform is a password-named expression (password, newPassword, user.password, $_POST['password'], getPassword(), optionally wrapped in .encode(), .getBytes() or []byte()):

  • Python base64.b64encode and friends, binascii.hexlify, codecs.encode, any .encrypt(...);
  • JavaScript btoa, Buffer.from(...).toString('base64'|'hex'), CryptoJS.AES/DES/TripleDES/RC4/Rabbit.encrypt, cipher.update;
  • Java Base64.getEncoder().encode/encodeToString, cipher.doFinal, .encrypt;
  • PHP base64_encode, openssl_encrypt, str_rot13;
  • Ruby Base64.encode64/strict_encode64/urlsafe_encode64;
  • Go base64.*.EncodeToString, hex.EncodeToString, an AEAD Seal of the password.

A function named decrypt_password, decryptPassword or DecryptPassword, defined or called, is also reported.

user.password = base64.b64encode(password.encode()).decode()   # flagged
token = Fernet(settings.KEY).encrypt(password.encode())        # flagged
const enc = CryptoJS.AES.encrypt(password, process.env.KEY).toString();   // flagged

Not flagged: HTTP Basic credentials (a line that builds user:password or names Basic), a password used as the key or as input to a key-derivation function, encoding of a hash, salt or digest, names that only contain the word (passwordFieldId), comments, strings and test code.

Remediation

import bcrypt
user.password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt())

Replace any “send me my password” flow with a time-limited reset link.

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

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

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