VNX-167: Improper Handling of Additional Special Element
Reports a key=value or user:secret string split on every '=' or ':' and unpacked into a fixed number of names, which fails (Python) or truncates the value (JavaScript) when the value holds an additional separator.
| Field | Value |
|---|---|
| Rule ID | VNX-167 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Python, JavaScript / TypeScript |
| CWE | CWE-167 |
| 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 | additional-special-element parsing cwe-167 |
| Source | internal/sast/rules/vnx-167.rego |
Overview
VNX-167 maps to CWE-167: Improper Handling of Additional Special Element. It reports a string split on every = or : whose pieces are unpacked into a fixed number of names:
- Python
k, v = s.split("="), also throughmap(str.strip, s.split("="))or a generator,for k, v in (p.split("=") for p in ...)anddict(x.split("=") for x in ...), which raiseValueErrorwhen the value contains another=; - JavaScript/TypeScript
const [user, pass] = s.split(":"), with or without a limit, an elided first element ([, pass]) or a trailing.map(...), which silently keeps only the text up to the second separator.
Not reported: a bounded split (split(sep, 1), maxsplit=1, rsplit(sep, 1)), str.partition, a regex split, a rest element ([k, ...rest]), a single destructured name, a split kept as a list, hours, minutes clock parsing, other separators, an unpack inside a Python try block, test files, comments and string literals.
Why This Matters
Values legitimately contain the separator: base64 ends in =, passwords contain :, IPv6 addresses are full of colons. In Python the unexpected element turns a request into an unhandled exception; in JavaScript a Basic-auth password a:b becomes a, and a token abc== loses its padding, so the program acts on a value the sender never sent.
What Gets Flagged
# FLAGGED
user, password = base64.b64decode(token).decode().split(":")
name, value = part.strip().split("=")
key, value = map(str.strip, line.split("="))
// FLAGGED
const [user, pass] = Buffer.from(b64, 'base64').toString().split(':');
const [, password] = credentials.split(':');
# NOT FLAGGED: split once
key, value = line.split("=", 1)
key, _, value = line.partition("=")
Remediation
- Split once:
s.split(sep, 1)ors.partition(sep)in Python,s.slice(0, i)/s.slice(i + 1)withi = s.indexOf(sep)in JavaScript. - For host:port, split on the last colon (
rsplit(":", 1)) or use a URL/address parser.
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-167
// nosec vnx-167
Or record an ignore rule: vulnetix ignore add --rule vnx-167 --reason "...". See Suppressing findings.