VNX-784: Reliance on Cookies without Validation and Integrity Checking in a Security Decision
Role, admin or login-state cookies read through unsigned cookie APIs and used in a comparison or condition.
| Field | Value |
|---|---|
| Rule ID | VNX-784 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Python, JavaScript / TypeScript, PHP, Ruby, Java, Go, C# |
| CWE | CWE-784 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | cookie-auth-decision cwe-784 |
| Source | internal/sast/rules/vnx-784.rego |
Overview
VNX-784 maps to CWE-784: Reliance on Cookies without Validation and Integrity Checking in a Security Decision. It reports a raw cookie read whose name says it carries a privilege or a login state (admin, is_admin, role, user_role, staff, superuser, access_level, user_type, logged_in, authenticated, permissions and similar) when the value is compared or tested on the same line, or assigned to a variable that a condition uses within the next 15 lines.
Raw reads covered: Django/Flask request.COOKIES / request.cookies (and "logged_in" not in request.COOKIES), Bottle/Tornado get_cookie() without secret=; Express req.cookies (including destructuring), Koa ctx.cookies.get() without signed: true, Next.js cookies().get(); PHP $_COOKIE and filter_input(INPUT_COOKIE, ...), including an if (!isset($_COOKIE[...logged_in...])) gate; Rails cookies[...]; Spring @CookieValue and servlet Cookie.getName()/getValue(); Go r.Cookie() (also tested in the same if statement); ASP.NET Request.Cookies[...].
Not reported: signed or encrypted cookie APIs (req.signedCookies, cookies.signed/cookies.encrypted, get_signed_cookie, get_secure_cookie), server-side sessions, preference, consent and session-id cookies, a role cookie that is only displayed, an isset() check whose block only sets the cookie, and code that writes cookies.
Why This Matters
The browser controls every cookie. A user who edits admin=0 to admin=1 grants themselves the role the check is protecting.
What Gets Flagged
if request.COOKIES.get("admin") == "1": # FLAGGED
return render_admin(request)
const { role } = req.cookies; // FLAGGED
if (role === "admin") deleteUser(req.params.id);
Not flagged:
if (req.session.role === "admin") return next();
Remediation
- Keep roles and login state on the server (session store, database) and look them up from an authenticated session.
- If a cookie must carry a claim, sign or encrypt it (
cookies.signed,req.signedCookies, a verified JWT) and verify it before use.
References
- CWE-784: Reliance on Cookies without Validation and Integrity Checking in a Security Decision
- OWASP Session Management Cheat Sheet
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-784
// nosec vnx-784
Or record an ignore rule: vulnetix ignore add --rule vnx-784 --reason "...". See Suppressing findings.