CWE-269, Improper Privilege Management, covers a product that does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.
MITRE classes it as a broad weakness. Many more specific entries sit beneath it, including incorrect assignment, privilege dropping errors, and context switching errors. If you are triaging a finding and nothing narrower fits, this is often where it lands.
It affects anyone who builds software with more than one level of access: operating system components, services that run as root, admin consoles, multi-tenant applications, and CI systems.
How it happens
The verbs in the definition are a useful checklist. Privilege management can fail at four moments.
Assign. The actor gets a privilege it should not have. MITRE's example CVE-1999-1193 (Gold) is an untrusted user placed in the Unix wheel group.
Modify. A privilege changes in a way that is wrong. CVE-2001-0128 (Gold) does not properly compute roles.
Track. The system forgets to remove or update a privilege. CVE-2001-1555 (Gold) is a case where terminal privileges are not reset when a user logs out, so the next person inherits them.
Check. The privilege exists but is not honored or verified when it matters. CVE-2001-1514 (Gold) does not properly pass the security context to child processes in certain cases, which allows privilege escalation.
Here is a small example of the track failure in application code:
# Vulnerable: the elevated flag is set and never cleared
def run_as_admin(user, action):
user.is_admin = True
result = action()
return result # exception path also leaves is_admin = True
If action() raises, or if the object is long lived, the elevation persists for later requests.
What an attacker gains
MITRE lists gaining privileges or assuming identity. In practice that means reaching functions and data outside the attacker's role. Depending on where the weakness sits, it can mean administrative operations, other users' accounts, or the ability to run actions as a more trusted identity.
The danger of this class is that the damage is bounded only by what the elevated identity can do. A low severity looking bug in a root process is not low severity.
How to find it
MITRE notes that automated static analysis, often called SAST, can find some instances of this weakness by analyzing source code or binaries. Treat it as a partial net. Add these checks:
- Map every place the program raises, lowers, or changes privilege, and read each one for the error path.
- Look for state that holds a privilege: flags, roles on session objects, thread local identities, environment variables. Ask where each is reset.
- Test across boundaries, not within them: log out and log in as someone else, spawn a child process, switch tenants, and see what carries over.
- Review how child processes and helper services receive their security context.
- Run the application as a low privilege user and as a normal customer role, and attempt each admin action.
How to fix it
- Run with least privilege by default. Give each process, role, and token only what it needs, and add rights deliberately.
- Make privilege scoped. Tie an elevation to one operation, then end it in a finally block so it cannot persist.
- Centralize the decision. One well tested function that answers "may this actor do this" is easier to get right than checks scattered through the code.
- Pass context explicitly. Do not rely on ambient state that child processes or callbacks may or may not inherit.
- Reset at boundaries. Clear privileges at logout, session change, and context switch.
- Review privilege changes. Log every grant and change, and alert on unexpected ones.
The earlier example, fixed:
from contextlib import contextmanager
@contextmanager
def elevated(user):
user.is_admin = True
try:
yield
finally:
user.is_admin = False
def run_as_admin(user, action):
with elevated(user):
return action()
Try it yourself
Pick one service you run as root or as an administrator account. Write down why it needs that level, which single operation requires it, and what it would take to drop to a normal account after that operation. If you cannot answer the middle question, that is your first CWE-269 finding.
Quick check
Why is CWE-269 described as a class and not a single bug?
It names the broad failure of managing privileges, whether in assigning, modifying, tracking, or checking them. More specific weaknesses, such as incorrect assignment or dropping errors, are narrower forms of the same problem.
What is wrong with setting an admin flag and clearing it later without a finally block?
If an error occurs between the two steps, the flag is never cleared and the elevation outlives the operation. Scoped elevation with guaranteed cleanup avoids that.
Sources
- MITRE CWE-269: https://cwe.mitre.org/data/definitions/269.html
- Safeguard Gold entry: https://gold.safeguard.sh/cwe/CWE-269