Broken access control is the risk OWASP found in every application it tested, and it sits at number one in the OWASP Top 10:2025 as A01:2025 Broken Access Control. The category covers any way a user, service or API client can act outside its intended permissions: reading another customer's record by changing an identifier, calling an admin function as a normal user, or making the server fetch an internal URL on an attacker's behalf. This guide goes deeper than the OWASP Top 10 overview: it explains what the 2025 category contains, the requirements that close it, how to implement and test them, what evidence an assessor will ask for, and where machine identities and API tokens fit. It is written for application security engineers, developers, architects and testers.
Key takeaways
- Still number one in 2025. OWASP reports that 100% of the applications tested had some form of broken access control, with 1,839,701 recorded occurrences and 32,654 related CVEs across 40 mapped CWEs.
- SSRF now lives here. Server-side request forgery (CWE-918), a separate category in 2021, has been rolled into A01:2025, so outbound request controls are now part of access control work.
- Enforce on the server, once, by default. Deny by default, build the check once and reuse it, and enforce it only in trusted server-side code that the caller cannot modify.
- Object-level checks are where most failures hide. Checking that a user may call an endpoint is not enough; every request must also confirm the caller may act on that specific record.
- Machine callers need the same rules. Service accounts, API keys and workload roles often bypass user-level authorisation, which turns one SSRF or leaked token into broad data access.
What it is and who it applies to
OWASP defines access control as the policy that stops users acting outside their intended permissions. When it fails, the result is unauthorised disclosure, modification or destruction of data, or a user performing a business function they should not be able to perform. Authentication answers "who are you"; access control answers "may you do this, to this object, now". A01 is about the second question, and it applies to every application that has more than one kind of user, more than one tenant, or any data that is not public.
The OWASP Top 10:2025 was built from testing data covering more than 2.8 million applications plus a community survey. For A01 the data shows a maximum incidence rate of 20.15%, an average incidence rate of 3.74% and an average weighted exploit score of 7.04. It has the most occurrences in the contributed data and the second highest number of related CVEs of any category. OWASP calls out CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor), CWE-201, CWE-918 (SSRF) and CWE-352 (Cross-Site Request Forgery) as notable mappings.
It applies to:
- Web applications and APIs: any route, controller, GraphQL resolver or serverless function that returns or changes data.
- Multi-tenant SaaS: where a missing tenant filter exposes one customer's data to another. See the Multi-Tenant SaaS Architecture Security Guide.
- Back-end services that make outbound requests: URL fetchers, webhooks, PDF renderers and image proxies, which are now in scope through SSRF.
- Static and stored resources: files in web roots, object storage buckets and database back ends exposed directly to clients.
Structure and key requirements
OWASP lists eight common forms of the weakness. The table maps each to the typical CWE and the control that closes it.
| Form of broken access control | Typical CWE | What it looks like | Control that closes it |
|---|---|---|---|
| Missing least privilege, open by default | CWE-732, CWE-284 | Endpoint or bucket readable by anyone when it should be limited to a role | Deny by default; explicit grants per role, attribute or relationship |
| Check bypass by tampering | CWE-639 | Altering URL, parameters, application state or API request body | Never trust client-supplied identity or role fields; derive from the session |
| Insecure direct object reference (IDOR) | CWE-639, CWE-566 | Changing acct= or an order ID returns another user's data | Ownership or relationship check on every object access |
| Unprotected API methods | CWE-285 | POST, PUT or DELETE lack the check that GET has | Central middleware applied to every method and route |
| Privilege escalation | CWE-269 | Anonymous user acts as logged in, or user acts as admin | Function-level checks on server; separate admin surface |
| Metadata tampering | CWE-639, CWE-565 | Replaying or editing JWTs, cookies or hidden fields | Signed, short-lived tokens validated server-side; server-side session invalidation |
| CORS misconfiguration | CWE-942 | API trusts any Origin with credentials | Fixed allowlist of origins (ASVS V3.4.2) |
| Forced browsing and path traversal | CWE-22, CWE-425 | Guessing admin URLs, reading files outside the web root | Route-level authorisation, canonicalised paths, no directory listing |
| Server-side request forgery | CWE-918, CWE-441 | Server fetches internal or metadata URLs supplied by a caller | Outbound allowlists (ASVS V13.2.4, V13.2.5), network egress control |
OWASP's prevention list reduces to ten requirements:
- Deny by default, except for genuinely public resources.
- Implement access control once and reuse it across the application, and keep CORS usage to a minimum.
- Enforce record ownership rather than accepting that a user can create, read, update or delete any record.
- Enforce business limits through domain models, not scattered conditionals.
- Disable directory listing and keep metadata such as
.gitand backup files out of web roots. - Log access control failures and alert administrators on patterns such as repeated failures.
- Rate limit APIs and controllers to slow automated enumeration.
- Invalidate server-side sessions at logout; keep JWTs short-lived and use refresh tokens with OAuth revocation where longer access is needed.
- Use established toolkits that offer declarative access control.
- Include access control tests in unit and integration suites.
The OWASP Authorization Cheat Sheet adds two design points worth adopting: prefer attribute-based (ABAC) or relationship-based (ReBAC) models over pure role-based access control, because roles alone cannot express "only the creator may edit this post" and lead to role explosion, and do not rely on random or obscured IDs as a control. See the Authorisation Models Guide and the Policy-as-Code for Authorisation Guide.
The ASVS 5.0 requirements behind A01
| ASVS 5.0 ID | Level | Requirement (summarised) |
|---|---|---|
| V8.1.1 | L1 | Authorisation documentation defines function-level and data-specific access rules |
| V8.2.1 | L1 | Function-level access restricted to consumers with explicit permissions |
| V8.2.2 | L1 | Data-specific access restricted to explicit permissions on specific items (IDOR and BOLA) |
| V8.2.3 | L2 | Field-level access restricted to explicit permissions (broken object property level authorisation) |
| V8.3.1 | L1 | Authorisation enforced at a trusted service layer, not in controls the client can manipulate |
| V8.3.3 | L3 | Access based on the originating subject's permissions, not those of an intermediary service |
| V8.4.1 | L2 | Multi-tenant applications use cross-tenant controls |
| V3.4.2 | L1 | CORS Access-Control-Allow-Origin is fixed or validated against an allowlist |
| V13.2.4 / V13.2.5 | L2 | Allowlists for external resources the application and server may contact (SSRF) |
See the OWASP ASVS Guide for how to choose a verification level.
Identity and NHI requirements
Access control failures are identity failures: the system misjudged what a subject was allowed to do. Non-human identities make the impact larger because they usually hold broad, standing access and are rarely covered by user-facing authorisation logic.
- SSRF turns into credential theft: when a server can be made to call a cloud metadata endpoint, it returns the workload's own role credentials. In the Capital One breach an SSRF against a misconfigured web application firewall returned temporary credentials for its cloud role, and that role could list and read S3 buckets holding customer data. On AWS, require IMDSv2 (
--http-tokens required), which needs a session token obtained with aPUTrequest and keeps the default hop limit of 1. - Confused deputy: CWE-441 is mapped to A01. When a back-end service calls another service with its own broad credentials, the downstream check sees the service, not the user. ASVS V8.3.3 requires decisions on the originating subject's permissions; pass the user context (for example an OAuth token exchange or a signed user claim) rather than relying on a privileged service account.
- Over-privileged service roles: scope workload roles to the specific buckets, tables and actions they need. See the OWASP NHI Top 10 NHI5 Overprivileged NHI Guide.
- Client-embedded keys need server-side policy: a publishable or anonymous key in browser JavaScript is effectively public. The Moltbook database exposure happened because row level security was not configured behind a key shipped in client code.
- API tokens and JWTs: validate signature, audience, issuer and expiry on every call, keep them short-lived and support revocation. See the JWT Security Guide.
Implementation steps
- Write the authorisation model down. For each resource type list who may perform each action and under what conditions (owner, tenant, role, attribute). This is ASVS V8.1.1 and it is the test oracle for everything that follows.
- Inventory every entry point. Enumerate routes, methods, GraphQL resolvers, message handlers and file paths from the code and the API gateway, including undocumented and legacy ones.
- Centralise enforcement. Put the check in middleware, a policy decision point or framework annotations that apply by default, so a new route without a policy fails closed. Avoid hand-written checks in each controller.
- Add object-level checks. Load records through queries scoped by the authenticated subject and tenant (for example
WHERE owner_id = :session_user), never by a client-supplied ID alone. In databases that support it, add row level security as a second layer. - Lock down outbound requests. Route server-side fetches through one component with a destination allowlist, block link-local and private ranges at the network layer, and require IMDSv2 or equivalent on cloud workloads. See the SSRF Prevention Guide.
- Fix CORS and static content. Replace reflected or wildcard origins with a fixed list, disable directory listing, and move files that need protection behind the same authorisation layer. See the CORS Misconfiguration Guide.
- Test in a pilot service first. Run the new policy layer in log-only or shadow mode, compare its decisions with current behaviour, fix legitimate flows it would block, then switch to enforce. Keep a feature flag so a broken policy can be rolled back to the previous decision path without a redeploy.
- Automate regression tests. Add tests that call each endpoint as anonymous, as a user of another tenant, as a low-privilege role and as the owner, and assert the expected allow or deny. Run them in CI on every change.
- Log and alert. Emit a structured event for every denial with subject, resource, action and decision, and alert on bursts of denials from one subject or sequential ID access.
Choosing an enforcement approach
| Approach | Fits | Trade-off |
|---|---|---|
| Framework annotations or middleware (RBAC) | Small teams, one application, few roles | Simple, but object-level rules end up in code and role counts grow |
| Library-based ABAC or ReBAC in the application | Products with ownership, sharing and tenancy rules | Expresses object rules well; policy still deployed with each app |
| Externalised policy decision point (policy as code) | Many services, shared rules, audit needs | Consistent and testable, but adds latency and an availability dependency |
| Database row level security | Direct client-to-database architectures, defence in depth | Strong backstop; easy to misconfigure or leave disabled |
Small organisations get most value from one well-tested middleware layer plus object-scoped queries. Large organisations with many services usually need an externalised decision point so that rules are written once and audited centrally.
Evidence and assessment
Automated scanners find little of A01 because they do not know who should be allowed to see what. Effective testing uses at least two accounts per role and tenant and swaps identifiers between them.
| Test (OWASP WSTG v4.2) | What the tester does | Evidence to keep |
|---|---|---|
| 4.5.1 Testing Directory Traversal File Include (WSTG-ATHZ-01) | Manipulates file path parameters to reach files outside the intended directory | Requests and responses, affected parameters |
| 4.5.2 Testing for Bypassing Authorization Schema (WSTG-ATHZ-02) | Calls each function unauthenticated and as other roles | Role-by-endpoint matrix with results |
| 4.5.3 Testing for Privilege Escalation (WSTG-ATHZ-03) | Alters role, group or account parameters to gain higher rights | Before and after privilege state |
| 4.5.4 Testing for Insecure Direct Object References (WSTG-ATHZ-04) | Swaps object IDs between two users and tenants | Pairs of IDs and the data returned |
An assessor or auditor will typically ask for: the documented authorisation model; the list of endpoints with their policy; CI results for authorisation tests; penetration test reports covering the WSTG authorisation tests; access control failure logs and alert rules; and records of periodic access reviews for administrative and service accounts. For API-specific depth see the OWASP API Top 10 API1 Broken Object Level Authorization Guide and the OWASP API Top 10 API5 Broken Function Level Authorization Guide.
Detection and metrics
- Monitor: HTTP 401 and 403 rates per subject, sequential or high-cardinality ID access by one session, requests from servers to metadata or private address ranges, CORS preflights from unexpected origins, and cloud data access by workload roles outside their usual pattern.
- Metric 1: percentage of routes covered by the central policy layer (target 100%, with new routes failing closed).
- Metric 2: percentage of endpoints with automated cross-user and cross-tenant tests.
- Metric 3: number of A01 findings per penetration test and bug bounty period, trending down.
- Metric 4: median time to fix confirmed access control findings.
- Metric 5: percentage of cloud workloads with IMDSv2 or equivalent enforced.
Mapping to other frameworks
| Framework | Reference | Relevance to A01 |
|---|---|---|
| OWASP ASVS 5.0 | V8 Authorization; V3.4.2; V13.2.4, V13.2.5 | Verifiable requirements for function, data and field-level access, CORS and outbound allowlists |
| OWASP API Security Top 10 2023 | API1, API3, API5 | Object, property and function-level authorisation in APIs |
| NIST SP 800-53 Rev 5 | AC-3 Access Enforcement; AC-6 Least Privilege; AC-4 Information Flow Enforcement; AC-24 Access Control Decisions | Enforcement, least privilege, controlling outbound flows (SSRF) |
| NIST CSF 2.0 | PR.AA-05 | Access permissions defined, managed, enforced and reviewed with least privilege |
| CIS Controls v8.1 | Control 6 Access Control Management; Control 16 Application Software Security | Access rules for accounts and secure development practice |
| ISO/IEC 27001:2022 Annex A | 5.15 Access control; 5.18 Access rights; 8.2 Privileged access rights; 8.3 Information access restriction | Policy and technical restriction of access to information |
| MITRE ATT&CK v20 | T1190 Exploit Public-Facing Application; T1078.004 Cloud Accounts; T1530 Data from Cloud Storage | How attackers use access control flaws and stolen workload credentials |
Common pitfalls
- Front-end only checks: hiding a button or disabling a route in JavaScript does nothing when the attacker calls the endpoint directly. OWASP's third example scenario is exactly this.
- Sequential IDs with no ownership check: in the McHire default password flaw an internal API returned any applicant's record for a sequential
lead_idwithout checking the caller's entitlement. Random IDs would have slowed enumeration, not fixed it. - Checking the endpoint, not the object: the role check passes, but the query loads any record matching the supplied ID, including other tenants' data.
- Inconsistent methods: GET is protected while PUT and DELETE on the same resource are not, often because they were added later.
- Trusting the service account: internal services call each other with full privileges, so one SSRF or compromised service reads everything. The Capital One role could read far more than a firewall needs.
- Database without policy: exposing a database API to the browser with row level security disabled, as in the Moltbook case, grants full access to whoever holds the public key.
Practitioner checklist
- Document the authorisation model for every resource type, including ownership, tenancy and field-level rules.
- Route all requests through one central, deny-by-default enforcement layer, and make unregistered routes fail closed.
- Scope every data query by the authenticated subject and tenant; never by a client-supplied ID alone.
- Protect every HTTP method and GraphQL operation, not just reads.
- Restrict server-side outbound requests to an allowlist and enforce IMDSv2 or equivalent on cloud workloads.
- Replace wildcard or reflected CORS origins with a fixed allowlist; disable directory listing and remove
.gitand backups from web roots. - Give service accounts and workload roles only the resources they need, and propagate user context to downstream services.
- Run automated cross-user and cross-tenant tests in CI, plus the four WSTG authorisation tests in each penetration test.
- Log every denial in a structured format, alert on bursts and enumeration, and keep short-lived, revocable tokens.
Standards and references
- OWASP: A01:2025 Broken Access Control
- OWASP: Top 10:2025 Introduction
- OWASP Cheat Sheet Series: Authorization Cheat Sheet
- OWASP: Web Security Testing Guide v4.2, Authorization Testing
- OWASP: Application Security Verification Standard
- NIST: SP 800-53 Rev. 5 Security and Privacy Controls
- AWS: Use the Instance Metadata Service to access instance metadata
Related NHI Mgmt Group resources: OWASP Top 10 Guide · Broken Access Control Prevention Guide · OWASP Top 10 A02 Guide · SSRF Prevention Guide · Authorisation Models Guide