CWE-565 covers applications that make security decisions from cookie values without checking that the value is genuine for the user.
Cookies live on the client. The user controls them. Anyone can open browser developer tools and change a cookie, or write a script that sends whatever cookie it likes. If your server believes the cookie, your server is trusting the attacker.
This hits web applications in any language. MITRE lists it as Not Language-Specific.
How it happens
The pattern is simple. The server stores something in a cookie, such as a role, an account ID or a "logged in" flag. On the next request it reads the cookie and acts on it.
MITRE's example reads a role from a cookie in Java:
// Vulnerable: role comes straight from a client cookie
Cookie[] cookies = request.getCookies();
String userRole = null;
for (Cookie c : cookies) {
if (c.getName().equals("role")) {
userRole = c.getValue();
}
}
if ("admin".equals(userRole)) {
showAdminPanel();
}
Nothing ties that cookie to the logged in user. Edit role=user to role=admin and the check passes.
The record cites a real pattern: CVE-2008-5784, an e-dating application that allowed admin privileges by setting the admin cookie to 1. You can see it on the Gold page for CVE-2008-5784.
Encryption alone is not the whole answer either. MITRE warns that cross site scripting or other attacks may let an attacker steal a strongly encrypted cookie that still passes integrity checks, and then replay it.
What an attacker gains
MITRE lists two groups of consequences.
- Confidentiality, integrity and availability. Attackers can modify application data and, depending on how the value is used, execute unauthorized code or commands. MITRE notes that attackers can easily change cookies in the browser or from client code outside the browser.
- Access control. Gain privileges or assume identity. MITRE calls out setting a user's privileges through a cookie as dangerous, since it can be manipulated to reach an administrative level.
If the cookie holds an account number, changing it can also mean acting as another user.
How to find it
The record lists automated static analysis as a detection method, noting it can find some instances.
Beyond that, a few simple checks help:
- Grep for cookie reads in authorization code. Search for
getCookies,request.cookiesor similar next to words like role, admin, level or userId. - Tamper with cookies in a test. Log in as a low privilege user, change each cookie value, and see whether access changes.
- Review session design. Ask where the server stores who the user is and what they may do. If the answer is "in a cookie", dig in.
- Dynamic testing. A web scan that mutates cookies can flag changed behavior.
How to fix it
MITRE's mitigations, in plain steps:
- Avoid using cookie data for security decisions. This is the first and best option.
- If you must use it, validate on the server. Perform thorough server side input validation on the cookie data.
- Add integrity checks to detect tampering. A signed value, using a keyed hash with a secret the client never sees, stops casual edits.
- Protect critical cookies from replay. Enforce timeouts so a stolen cookie is valid only briefly, and include an unpredictable server side value in your integrity check that is not exposed to the client.
The better design keeps authority on the server. Store a random session identifier in the cookie and keep the role in server side session state:
// Fixed: cookie carries only an opaque session ID
HttpSession session = request.getSession(false);
if (session == null) { response.sendError(401); return; }
User user = (User) session.getAttribute("user");
if (user != null && user.hasRole("admin")) {
showAdminPanel();
} else {
response.sendError(403);
}
The session ID is random and meaningless on its own. The role lives where the client cannot touch it. Mark the session cookie HttpOnly and Secure, and use a sensible expiry.
Frameworks usually handle this well when you use their session features. The bugs tend to appear when someone adds a convenience cookie for speed. Keeping the framework up to date matters too. The free scan at gold.safeguard.sh/scan lists your dependencies in the browser, with no login and the file staying on your machine, up to 100 dependencies.
Try it yourself
Click through it at your own pace, or open it full screen.
Quick check
Why is a role stored in a cookie dangerous?
The user controls the cookie. They can change the value and the server will believe it unless it is verified.
Does encrypting the cookie solve it?
Not fully. MITRE warns that a stolen encrypted cookie that passes integrity checks can be replayed, so timeouts and server side values still matter.
What is the safest design?
Keep roles and identity in server side state and send the client only an opaque session identifier.