VNX-493: Critical Public Variable Without Final Modifier
A public field that any code can overwrite holds security- or business-critical data: in Java a public field without final, in C# a public field without readonly or const, whose name says it is a password, passphrase, secret, API key, private key, token, credential, an admin flag, role, permission or privilege, or a price, balance, amount or salary. Any class can change it, so a check that reads it can be steered. Static and instance fields are both reported. Not reported: final, readonly and const fields, C# properties ({ get; ... } or =>), private, protected and package-private fields (package scope is VNX-487), constants that name a parameter or header rather than hold the value, methods, test code, and the pattern in comments or string literals.
| Field | Value |
|---|---|
| Rule ID | VNX-493 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Java, C# |
| CWE | CWE-493 |
| 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 | critical-public-variable final readonly cwe-493 |
| Source | internal/sast/rules/vnx-493.rego |
Overview
VNX-493 maps to CWE-493: Critical Public Variable Without Final Modifier. It reports public, writable fields whose names mark them as critical: credentials, privilege flags and money.
Why This Matters
A public field without final (Java) or readonly (C#) can be reassigned by any code that can see the class. A static one is shared process-wide. If an authorization check reads Settings.isAdmin, or a checkout reads product.price, whoever can write the field decides the outcome.
What Gets Flagged
public static String DB_PASSWORD = System.getenv("DB_PW"); // FLAGGED
static public boolean isAdmin = false; // FLAGGED
public float price; // FLAGGED
public static final String PASSWORD_PARAM = "password"; // not flagged
public static string ConnectionPassword = ""; // FLAGGED
public decimal Price; // FLAGGED
public decimal Price { get; private set; } // not flagged: property
public static readonly string ApiKeyName = "key"; // not flagged
Remediation
- Make the field
privateand expose a getter (and, only where needed, a validated setter). - If the value never changes after initialisation, declare it
final/readonly. - Keep credentials out of fields altogether; read them from a secret store when needed.
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-493
// nosec vnx-493
Or record an ignore rule: vulnetix ignore add --rule vnx-493 --reason "...". See Suppressing findings.