Skip to content

CWE-315: Cleartext Storage of Sensitive Information in a Cookie is a common security vulnerability where sensitive data, such as Personally Identifiable Information (PII), is stored in web cookies without adequate protection. This practice can lead to unauthorized access and misuse of sensitive data. This article explores the risks associated with PII exposure through CWE-315 and provides remediation strategies with coding examples in Java, JavaScript, and Python.

  1. Unauthorized Access: If cookies are intercepted, sensitive data can be accessed by unauthorized parties.

  2. Session Hijacking: Storing session identifiers in cleartext cookies can lead to session hijacking if the cookies are captured.

  3. Identity Theft: Exposure of PII can enable identity theft, allowing attackers to impersonate the victim.

  1. Reputational Damage: A breach of privacy can damage an organization’s reputation, resulting in loss of customer trust and business.

  2. Legal Consequences: Non-compliance with privacy regulations like GDPR or CCPA can lead to legal penalties.

  3. Resource Drain: Dealing with breaches and improving security post-incident can consume significant organizational resources.

Effective management of cookies is critical to preventing PII exposure. Strategies include omitting sensitive data from cookies, masking data, and using strong encryption methods to protect any sensitive information that must be stored in cookies.

Avoid storing sensitive data in cookies altogether.

Java
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
public class CookieManager {
public void createSessionCookie(HttpServletResponse response, String sessionId) {
Cookie cookie = new Cookie("session", sessionId);
response.addCookie(cookie);
// No sensitive PII is stored in the cookie
}
}
Javascript
// Express: HttpOnly cookies can only be set server-side, never via document.cookie
function setSessionCookie(res, sessionId) {
res.cookie('session', sessionId, { httpOnly: true, secure: true, sameSite: 'strict', path: '/' });
// Ensure that no sensitive PII is included in the cookie
}
Python
from http.cookies import SimpleCookie
def set_session_cookie(session_id):
cookie = SimpleCookie()
cookie['session'] = session_id
cookie['session']['httponly'] = True
print(cookie.output()) # No sensitive PII is stored in the cookie

If non-sensitive data must be stored in a cookie and there is a need to protect even that, masking can be used.

Java
import org.apache.commons.codec.digest.DigestUtils;
public class CookieUtility {
// PEPPER is loaded from your secret store, never hardcoded
private static final String PEPPER = System.getenv("USER_ID_PEPPER");
public String maskUserId(String userId) {
return "user-" + DigestUtils.sha256Hex(PEPPER + userId).substring(0, 12);
}
}
Javascript
const crypto = require('crypto');
// PEPPER is loaded from your secret store, never hardcoded
const PEPPER = process.env.USER_ID_PEPPER;
function maskUserId(userId) {
return 'user-' + crypto.createHash('sha256').update(PEPPER + userId).digest('hex').slice(0, 12);
}
Python
import hashlib
import os
# PEPPER is loaded from your secret store, never hardcoded
PEPPER = os.environ['USER_ID_PEPPER']
def mask_user_id(user_id):
return 'user-' + hashlib.sha256((PEPPER + user_id).encode()).hexdigest()[:12]

Encrypt any sensitive data before storing it in cookies to protect it from unauthorized access.

Java
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
public class SecureCookieUtility {
// secretKey is supplied by the caller, sourced from your KMS or secret store
public void encryptAndAddCookie(HttpServletResponse response, String data, SecretKey secretKey) throws Exception {
byte[] iv = new byte[12];
new SecureRandom().nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(128, iv));
byte[] encryptedData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
byte[] payload = ByteBuffer.allocate(iv.length + encryptedData.length).put(iv).put(encryptedData).array();
Cookie cookie = new Cookie("secureData", java.util.Base64.getEncoder().encodeToString(payload));
cookie.setHttpOnly(true);
response.addCookie(cookie);
}
}
Javascript
const crypto = require('crypto');
// Express: the cookie is set server-side so HttpOnly is actually honored
// key: 32-byte Buffer loaded from your KMS or secret store
function encryptAndAddCookie(res, data, key) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]);
const value = iv.toString('hex') + ':' + encrypted.toString('hex');
res.cookie('secureData', value, { httpOnly: true, secure: true, sameSite: 'strict', path: '/' });
}
Python
from cryptography.fernet import Fernet
from http.cookies import SimpleCookie
# key: Fernet key loaded from your secret store, never generated per call
def encrypt_and_add_cookie(data, key):
cipher = Fernet(key)
encrypted_data = cipher.encrypt(data.encode())
cookie = SimpleCookie()
cookie['secureData'] = encrypted_data.decode()
cookie['secureData']['httponly'] = True
print(cookie.output())

Addressing CWE-315 is essential for securing web applications against data theft and unauthorized access. By implementing the strategies of omitting, masking, and encrypting data in cookies, organizations can significantly enhance their security posture and ensure compliance with relevant data protection regulations. This not only protects the privacy of users but also helps maintain the integrity and trustworthiness of the application.