VNX-315: Cleartext Storage of Sensitive Information in a Cookie
A password, card number, CVV, SSN, PIN, bank account number or key written into a cookie in cleartext, by name or by value, across Python, Node, Java, PHP, Ruby and Go cookie APIs.
| Field | Value |
|---|---|
| Rule ID | VNX-315 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Go, Java, JavaScript / TypeScript, PHP, Python, Ruby |
| CWE | CWE-315 |
| CAPEC | CAPEC-97 |
| ATT&CK | T1557 |
| 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 | sensitive-cookie cleartext-storage cwe-315 |
| Source | internal/sast/rules/vnx-315.rego |
Overview
VNX-315 maps to CWE-315: Cleartext Storage of Sensitive Information in a Cookie. It reports a cookie whose name is a sensitive value (password, card number, CVV, SSN, PIN, bank account or routing number, IBAN, API, private or secret key), or whose value expression names a password, card number, CVV or SSN, set through:
- Flask/Django
set_cookieandset_signed_cookie(signed cookies are readable); - Express
res.cookie, Koactx.cookies.set, Fastifyreply.setCookie, js-cookieCookies.set,document.cookie = "password=..."; - Java
new Cookie(...)and SpringResponseCookie.from(...); - PHP
setcookieandsetrawcookie; - Rails
cookies[...],cookies.permanentandcookies.signed; - Go
http.Cookie{Name: ..., Value: ...}, on one line or several.
Not reported: values passed through a hash, encryption, HMAC or masking call; Rails cookies.encrypted; cookies being cleared (empty value or None); session ids, auth tokens, CSRF tokens and other identifiers; test files and comments.
Why This Matters
A cookie lives in the browser profile, is readable by any script on the page unless it is HttpOnly, is sent with every request, and ends up in proxy and server logs. A password or card number stored there is exposed to anyone with access to the device, the logs or an XSS.
What Gets Flagged
# FLAGGED
resp.set_cookie("password", request.form["password"], max_age=86400)
// FLAGGED
res.cookie('creds', JSON.stringify({ username, password }));
document.cookie = "password=" + pwd + "; path=/";
# FLAGGED
cookies[:password] = params[:password]
Not flagged: res.cookie('session_token', token), cookies.encrypted[:password] = params[:password], setcookie('password', '', time() - 3600).
Remediation
- Keep sensitive values on the server, keyed by an opaque session identifier.
- If something must travel in a cookie, encrypt it with an authenticated cipher (Rails
cookies.encrypted, a server-side key) and mark the cookieSecure,HttpOnlyandSameSite. - Never put passwords in a “remember me” cookie: issue a random, revocable remember token instead.
References
- CWE-315: Cleartext Storage of Sensitive Information in a Cookie
- 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-315
// nosec vnx-315
Or record an ignore rule: vulnetix ignore add --rule vnx-315 --reason "...". See Suppressing findings.