Safeguard
Application Security•

CWE-565 Reliance on Cookies Without Validation: Fix Guide

Trusting a cookie value for roles or access lets users edit their own privileges. See how CWE-565 happens and how to fix it.

Safeguard Security Team
5 min read

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.cookies or 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:

  1. Avoid using cookie data for security decisions. This is the first and best option.
  2. If you must use it, validate on the server. Perform thorough server side input validation on the cookie data.
  3. Add integrity checks to detect tampering. A signed value, using a keyed hash with a secret the client never sees, stops casual edits.
  4. 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.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.