Skip to content

VNX-591: Password read into a char[] copied into an immutable String

Reports Java code that copies a password returned as char[] (Console.readPassword, JPasswordField/PasswordCallback/KeyStore.PasswordProtection getPassword) into an immutable String, or reads JPasswordField.getText(), so the secret can no longer be wiped from memory.

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

Overview

VNX-591 maps to CWE-591: Sensitive Data Storage in Improperly Locked Memory. Java cannot lock memory against paging or core and heap dumps. The one control the platform offers for a password is to keep it in a char[] and overwrite the array once it has been used. The JDK’s password APIs return char[] for exactly this reason.

The rule reports the line that throws that control away: new String(...), String.valueOf(...) or String.copyValueOf(...) applied to Console.readPassword(), to getPassword() of JPasswordField, PasswordCallback or KeyStore.PasswordProtection, or to a char[] variable assigned from one of those within the 15 lines above. It also reports the deprecated JPasswordField.getText(), which returns a String.

It does not report a char[] that is used and wiped without becoming a String, a getPassword() of an application class that already returns a String, new String over other byte or char arrays, or comments and string literals. Native memory locking (mlock, VirtualLock) in C/C++ is not analysed.

Why This Matters

A String is immutable and is collected whenever the garbage collector chooses. Until then the password sits in the heap, where it can be paged to swap, written into a heap dump or crash dump, or read by anything that can inspect the process. A char[] can be cleared the moment authentication finishes.

What Gets Flagged

// FLAGGED: the password becomes an immutable String
String password = new String(console.readPassword("Password: "));

char[] secret = console.readPassword("Keystore password: ");
String asText = new String(secret);          // FLAGGED

String typed = new String(passwordField.getPassword());  // FLAGGED
String pin = pinField.getText();             // FLAGGED: JPasswordField.getText()

// NOT FLAGGED: the char[] is used and wiped
char[] pw = console.readPassword("Password: ");
try {
    verify(pw);
} finally {
    Arrays.fill(pw, '\0');
}

Remediation

  1. Keep the password in the char[] the API returned and pass that array to the code that needs it (PBEKeySpec, KeyStore.load, KeyManagerFactory.init all take char[]).
  2. Overwrite the array with Arrays.fill(pw, '\0') in a finally block once it has been used.
  3. Replace JPasswordField.getText() with getPassword().

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

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

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