VNX-1290: Security identifier decoded from client data without verification
Detects Python code that derives an identity by merely base64- or hex-decoding a cookie or an identity-bearing header, with no signature check, so a client can encode any identity. The software analogue of CWE-1290.
| Field | Value |
|---|---|
| Rule ID | VNX-1290 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Python |
| CWE | CWE-1290 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | incorrect-decoding security-identifier cwe-1290 |
| Source | internal/sast/rules/vnx-1290.rego |
Overview
VNX-1290 maps to CWE-1290: Incorrect Decoding of Security Identifiers. CWE-1290 is a hardware weakness: a bus decoder that maps an agent’s security identifier to the wrong agent. It has no direct source-code form, so the rule reports its nearest software analogue: decoding a security identifier from a value the client holds and trusting the result. Base64 and hex are encodings, not protection: any client can encode admin: or a pickled admin object.
Reported: b64decode, urlsafe_b64decode, standard_b64decode, b32decode, b16decode, decodebytes, binascii.a2b_base64 and bytes.fromhex applied to a cookie (Flask request.cookies, Django request.COOKIES, Bottle/Tornado get_cookie) or to a custom header whose name says it carries identity (token, session, auth, identity, user, jwt, sid), directly or through a variable assigned from one in the 10 lines above.
Not reported: a decode with an HMAC or signature check, compare_digest, itsdangerous, django.core.signing or a .verify() call within 10 lines before or 3 after; the Authorization header (Basic credentials are checked against a store afterwards); form fields and other data that is not an identifier; constants, comments and strings. Unverified JWT decoding is VNX-JWT-004.
What Gets Flagged
session_token = request.cookies.get("session")
username = base64.b64decode(session_token).decode().split(":")[0] # FLAGGED
claims = json.loads(urlsafe_b64decode(request.headers["X-Auth-Token"])) # FLAGGED
What Is Not Flagged
payload, _, sig = request.cookies.get("session", "").partition(".")
expected = hmac.new(SECRET, payload.encode(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig):
abort(403)
return base64.b64decode(payload).decode()
Remediation
- Use the framework’s signed session (Flask
session, Django sessions) or a signing library (itsdangerous,django.core.signing). - If a token must be hand-built, sign it with an HMAC and verify the signature with
hmac.compare_digestbefore decoding. - Never deserialise (pickle) a client-held value.
References
- CWE-1290: Incorrect Decoding of Security Identifiers
- CWE-565: Reliance on Cookies without Validation and Integrity Checking
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-1290
// nosec vnx-1290
Or record an ignore rule: vulnetix ignore add --rule vnx-1290 --reason "...". See Suppressing findings.