This weakness occurs when a system groups multiple actions or resources under a single permission, forcing users to grant broad access when they only need…
This weakness occurs when a system groups multiple actions or resources under a single permission, forcing users to grant broad access when they only need narrow capabilities. Instead of separate permissions for "read," "write," and "delete," for example, a single "edit" permission might allow all three—meaning anyone trusted to view content can also destroy it. This design flaw makes it difficult to follow the principle of least privilege and increases the blast radius of compromised accounts.
02How It Happens
Access control systems are often designed with convenience in mind, bundling related operations into coarse-grained roles or permissions. A developer might create a single "admin" role that grants access to user management, content editing, billing, and system configuration—when in reality, a content editor should never touch billing, and a billing clerk should never manage users. Similarly, a file-sharing application might grant "folder access" as an all-or-nothing permission, with no way to distinguish between read-only and write access. When permissions are not subdivided finely enough, the system cannot enforce the principle of least privilege, and any compromise of a user account or API token grants far more capability than necessary.
03Real-World Impact
Overly broad permissions increase the damage potential of account compromise. A stolen API key for a service integration might be intended only to read customer data, but if the same token grants write and delete permissions, an attacker can modify or erase records. Similarly, a disgruntled employee with "content editor" access might be able to delete critical pages or modify financial records if those actions fall under the same permission. In multi-tenant systems, insufficient granularity can allow one tenant to access or modify another tenant's data if the permission model does not distinguish between them. The result is often wider-than-necessary data exposure, unauthorized modifications, or service disruption.
Why it's vulnerable: The user_management permission grants view, edit, and delete capabilities equally. A user intended only to view user details can also delete users.
Fixed pattern
# Fixed: granular permissions for each action
def manage_user(user_id, action, request_user):
if action == "view" and request_user.has_permission("user_view"):
return get_user_details(user_id)
elif action == "edit" and request_user.has_permission("user_edit"):
return update_user(user_id, request.data)
elif action == "delete" and request_user.has_permission("user_delete"):
return delete_user(user_id)
else:
raise PermissionError("Access denied")
Vulnerable pattern
// Vulnerable: single role grants all content actions
function manage_content($content_id, $action, $user) {
if ($user->has_role("editor")) {
if ($action === "view") {
return get_content($content_id);
} elseif ($action === "publish") {
return publish_content($content_id);
} elseif ($action === "delete") {
return delete_content($content_id);
}
} else {
wp_die("Access denied");
}
}
Why it's vulnerable: The "editor" role permits viewing, publishing, and deleting content indiscriminately. A user who should only draft content can publish or delete it.
Fixed pattern
// Fixed: separate capabilities for each action
function manage_content($content_id, $action, $user) {
if ($action === "view" && $user->has_capability("read_content")) {
return get_content($content_id);
} elseif ($action === "publish" && $user->has_capability("publish_content")) {
return publish_content($content_id);
} elseif ($action === "delete" && $user->has_capability("delete_content")) {
return delete_content($content_id);
} else {
wp_die("Access denied");
}
}
05Prevention Checklist
Map permissions to individual actions. Define separate permissions for create, read, update, and delete operations rather than bundling them into a single role.
Use role-based access control (RBAC) with fine-grained capabilities. Assign users the minimum set of capabilities needed for their job function.
Audit existing roles and permissions. Review all user roles in your system and identify any that grant unnecessary access; split overly broad roles into smaller, more specific ones.
Implement attribute-based access control (ABAC) for complex scenarios. For multi-tenant or resource-specific access, use attributes (e.g., "user can edit only their own posts") rather than blanket role membership.
Test permission boundaries. Verify that users with one permission cannot perform actions requiring a different permission; use automated tests to catch regressions.
Document the permission model. Maintain clear documentation of what each permission grants, so developers and administrators understand the intended scope.
06Signs You May Already Be Affected
Review your system's role and permission definitions: if a single role or permission grants access to multiple unrelated actions (e.g., "admin" that covers user management, billing, and content), you likely have insufficient granularity. Check audit logs for unexpected actions by users—for example, a user with "read-only" access performing writes, or a user in one department accessing another's data. If your system has no way to restrict a user's access to a subset of resources (e.g., only their own files or a specific tenant's data), that is also a sign of coarse-grained control.