Skip to content

VNX-210: Self-generated Error Message Containing Sensitive Information

Detects errors the program raises itself whose message carries a secret value (password, secret, API key, private key, token, credential, DSN, connection string): Go fmt.Errorf/errors.New/http.Error/panic, Python raise/abort/HTTPException, Java throw new/sendError, JavaScript new Error/createError/res.status(4xx|5xx).

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-210
Severity Low
SARIF level note
Kind sast
Languages Go, Java, JavaScript / TypeScript, Python
CWE CWE-210
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 error-handling self-generated information-exposure cwe-210
Source internal/sast/rules/vnx-210.rego

Overview

VNX-210 maps to CWE-210: Self-generated Error Message Containing Sensitive Information. When code detects a failure and writes its own error message, it is easy to include the very value that failed: the rejected API key, the password that did not match, the DSN that would not connect. That message then travels to the client, to logs, to crash reporters and to monitoring, and the secret travels with it.

The rule reports an error construction whose message includes a secret’s value, outside any string literal: an argument, a concatenation, a %/.format()/String.format argument, or an f-string or template-literal interpolation. A value counts when its name ends in password, passwd, passphrase, pwd, secret, apiKey/api_key, privateKey, token, credential(s), dsn or connection string (cfg.Password, client_secret, refreshToken, tokenString, config.getPassword()).

Language Error constructions
Go fmt.Errorf, errors.New/Errorf/Wrap/Wrapf, status.Errorf, http.Error, panic, gin c.JSON/String/AbortWithStatusJSON with a 4xx/5xx status
Python raise X(...), abort(...), HTTPException(...)
Java throw new X(...), response.sendError(...), new ResponseStatusException(...)
JavaScript, TypeScript new Error(...) and every ...Error(...), createError(...), `res.status(4xx

What Gets Flagged

return fmt.Errorf("connect %s as %s/%s: %w", cfg.Host, cfg.User, cfg.Password, err)   // FLAGGED
return errors.New("api key rejected: " + apiKey)                                      // FLAGGED
raise PermissionError(f"unknown api key {api_key}")   # FLAGGED
throw new Error(`No session for token ${sessionToken}`);   // FLAGGED

What Is Not Flagged

  • The secret’s name only in the message text: throw new Error('password is required').
  • Metadata about a secret: password.length, len(password), secret.Name, tokenType, secretName, passwordLen.
  • Sentinel errors such as ErrInvalidToken, and values passed through a non-getter call (hash(password)).
  • A condition on the secret rather than its value: password ? 'rejected' : 'missing', tokenProvided: !!token.
  • Object keys ({ tmpToken: ... }), logging calls (covered by VNX-SEC-022 and the per-language logging rules), and test code.

Remediation

Say what failed, not what the value was.

return fmt.Errorf("connect %s as %s: %w", cfg.Host, cfg.User, err)

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

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

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