Safeguard
Application Security•

CWE-266 Incorrect Privilege Assignment: How It Happens and Fixes

CWE-266 is giving an actor a privilege it should not have. Real examples include untrusted users in the wheel group. Here is how to spot and prevent it.

Safeguard Security Team
3 min read

CWE-266, Incorrect Privilege Assignment, is a product that assigns a privilege to the wrong actor, creating an unintended sphere of control for that actor.

It hits anyone who writes installers, provisioning tools, admin consoles, or permission models. The flaw is not in a check that fails. The check works fine. The wrong thing was granted in the first place.

How it happens

Privilege assignment goes wrong in a few recurring ways, all visible in MITRE's observed examples:

  • A default grants too much. CVE-1999-1193 (Gold) is an untrusted user placed in the Unix wheel group.
  • Users can grant rights to themselves. CVE-2005-2741 (Gold) is a product that allows users to grant themselves certain rights, which can be used to escalate privileges.
  • The wrong identifier is used. CVE-2005-2496 (Gold) uses the group ID of a user instead of the group, so the program runs with different privileges.
  • A status is assigned by mistake. CVE-2004-0274 (Gold) mistakenly assigns a particular status to an entity, leading to increased privileges.

A web application version looks like this:

# Vulnerable: trusts a role sent by the client
@app.post("/signup")
def signup():
    user = User(email=request.form["email"],
                role=request.form.get("role", "member"))
    db.add(user)

Anyone can post role=admin.

What an attacker gains

MITRE lists gaining privileges or assuming identity. A user can reach restricted functionality and sensitive information, which may include administrative functions and other user accounts.

How to find it

  • Review every place that writes a role, group, or permission, and ask who is allowed to call it.
  • Diff the privileges of a brand new account against what the role is meant to have.
  • Search for code that copies request parameters into privilege fields.
  • Check installer scripts for default group memberships.

How to fix it

Decide privileges on the server from a trusted source, never from user supplied input.

@app.post("/signup")
def signup():
    user = User(email=request.form["email"], role="member")
    db.add(user)
  • Start every new account at the lowest privilege.
  • Separate the right to use a feature from the right to grant access to it.
  • Log every privilege change and review the log.
  • Test with a fresh account as part of your regular checks.

Quick check

Why is accepting a role field from a form a CWE-266 problem?

The server hands out a privilege based on a value the requester controls. The assignment is wrong even though no access check was bypassed.

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.