VNX-450: Multiple interpretations of input: a text flag read as a boolean by truthiness
Detects a configuration or request flag that arrives as text and is made boolean by truthiness, so 'false', '0' and 'no' all mean on: Python bool() of os.environ/getenv, request parameters, sys.argv or input(), os.environ.get with a True/False default, argparse type=bool, and Node Boolean()/!! of process.env/req.query or process.env.X || true/false.
| Field | Value |
|---|---|
| Rule ID | VNX-450 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Python, JavaScript / TypeScript |
| CWE | CWE-450 |
| 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 | multiple-interpretations truthiness configuration cwe-450 |
| Source | internal/sast/rules/vnx-450.rego |
Overview
VNX-450 maps to CWE-450: Multiple Interpretations of UI Input. An operator who sets APP_DEBUG=false, or a user who answers “no”, means off. Code that turns that text into a boolean by truthiness reads every non-empty string as on, silently choosing the less safe interpretation.
The rule reports:
- Python
bool()aroundos.environ/os.getenv, a Flask or Django request parameter (directly or through a variable assigned from one in the six lines above), orsys.argv, when the line names a switch (debug, enable, allow, skip, require, verify, secure, tls, csrf, auth, admin, public, include, notify, verbose, feature, flag…); andbool(input(...))always. - Python
os.environ.get(name, True|False)/os.getenv(name, True|False)that is not parsed: once set, the value is a non-empty string. - Node
Boolean(process.env.X)/Boolean(req.query.x)naming a switch, andprocess.env.X || true|falseor?? true|false.
Not reported: values parsed explicitly (strtobool, ==/!=, in (...), .lower(), int()), string defaults, bool() of a token, URL, path or DSN (a deliberate is-it-set test), bool() of ordinary values, comments, strings, docstrings and test files.
What Gets Flagged
# FLAGGED: WEB_DEBUG=false still enables debug
WEB_DEBUG = os.environ.get("WEB_DEBUG", True)
DEBUG = bool(os.environ.get("APP_DEBUG"))
parser.add_argument("--dry-run", default=False, type=bool)
# NOT FLAGGED: parsed explicitly
DEBUG = os.environ.get("APP_DEBUG", "false").lower() in ("1", "true", "yes")
// FLAGGED: STRICT_TLS=false is truthy
const strictTls = process.env.STRICT_TLS || true;
const allowSignup = !!process.env.ALLOW_SIGNUP;
Remediation
Parse flags explicitly against an accepted set (value.strip().lower() in {"1", "true", "yes", "on"}, process.env.X === 'true'), and use typed config loaders (getboolean, pydantic, envalid) where available.
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-450
// nosec vnx-450
Or record an ignore rule: vulnetix ignore add --rule vnx-450 --reason "...". See Suppressing findings.