Security & PermissionsA comprehensive checklist for testing role-based access control: page and route permissions, feature-level access, data visibility, API authorization, admin workflows, permission inheritance, audit logging, and security checks against privilege escalation and IDOR.
›When introducing a new role or modifying the permissions of an existing role
›After refactoring the authorization layer or migrating to a new access-control library
›As part of a security review before releasing an admin panel or multi-tenant feature
›When adding a new resource type (new entity, page, or API endpoint) to the system
›As a regression check after any change to the authentication or session system
Access control bugs are the most frequently exploited class of web vulnerability — OWASP ranks Broken Access Control as the #1 category. This checklist covers every layer: role definitions, page-level route guards, feature-level UI gating, data-level ownership checks (IDOR prevention), API authorization, admin and privileged workflows, permission change propagation, audit logging, and negative/security checks for privilege escalation. For each section, the tests must be run with real user accounts in each role — not just by inspecting code.
0/35
Role Definitions & Inventory
0/4
Start by documenting every role in the system and its expected permissions before executing any tests.
Page & Route Access Control
0/5
Verify that every protected page and route is inaccessible to roles that lack permission.
Feature & Action Permissions
0/5
Verify that feature-level controls (buttons, forms, bulk actions) are enforced both in the UI and the API.
Data Access & Visibility
0/4
Confirm that data is scoped correctly — users see only the records they are permitted to access.
API Authorization Checks
0/4
Validate API authorization independently from the UI — server-side checks must not rely on the frontend to suppress actions.
Permission Changes & Propagation
0/4
Verify that role changes take effect immediately and do not leave stale access windows.
Negative & Security Checks
0/6
Explicitly attempt bypass techniques and privilege escalation attacks to validate the authorization layer is robust.
Audit Logging
0/3
Verify that permission-sensitive actions are logged with enough detail to reconstruct what happened.
Common Bugs
IDOR — user can read another user's records by incrementing an integer ID in the URL
GET /invoices/1042 returns User A's invoice. GET /invoices/1041 returns User B's invoice. The server checks authentication (valid token) but not authorization (does this token own this resource). Fix: enforce row-level ownership checks on every GET, and prefer random UUIDs over sequential integer IDs.
Role change not reflected in active JWT — demoted admin retains access until token expires
Admin role is removed from User A. User A's current JWT still carries the 'admin' role claim and remains valid for its full TTL (e.g., 24 hours). User A continues to pass admin checks because the server trusts the JWT claim without checking the database. Fix: use short JWT TTLs + refresh tokens, or maintain a server-side role lookup on every request.
Mass assignment — setting role: 'admin' in a user-update request is silently accepted
The user-update endpoint binds all incoming request body fields to the user model without an allowlist. A standard user sends PATCH /users/:id with {"role": "admin"} and becomes an admin. Fix: use an explicit allowlist of permitted update fields — never bind the entire request body to a model directly.
Client-side role check is the only gate — removing a hidden button allows the action
The delete button is hidden via ng-if/v-show for non-admin users. An attacker inspects the DOM, finds the hidden button, enables it via DevTools, and clicks it — the API accepts the request because there is no server-side role check on the delete endpoint. Every write action must be authorized server-side.
Admin accounts default to enabled with well-known credentials after first install
After a fresh deployment, the admin account is created with default credentials (admin/admin, admin/password123). These are not rotated before the application goes live. Attackers systematically probe for default credentials on known admin paths. Always force credential rotation on first login.
storageState() lets you maintain separate authenticated sessions for each role, enabling parallel cross-role testing without re-logging in for every test.
Test API authorization independently from the UI with different role tokens. Collection-level variables let you swap between role tokens to run the same request collection as viewer, editor, and admin.
Intercept and modify requests to test privilege escalation, JWT tampering, mass assignment, and parameter pollution. Burp Repeater makes trying every HTTP method on every endpoint fast.
cy.session() with per-role fixtures makes it practical to test the same user journey as 4 different roles in a single spec file. Use cy.intercept() to verify 403 responses on API calls.