---
title: "OWASP Top 10 2025 A01, Part 2: Where Broken Access Control Actually Happens"
url: https://daily.dev/posts/owasp-top-10-2025-a01-part-2-where-broken-access-control-actually-happens-nhnsckylo
source_url: https://daily.dev/posts/owasp-top-10-2025-a01-part-2-where-broken-access-control-actually-happens-nhnsckylo
type: freeform
source: "Przemyslaw"
author: "Przemyslaw"
published: 2026-07-08T08:31:12.261Z
updated: 2026-07-08T08:31:35.773Z
tags: ["security", "authorization"]
reading_time: 7
upvotes: 1
comments: 0
language: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# OWASP Top 10 2025 A01, Part 2: Where Broken Access Control Actually Happens

**[Przemyslaw](https://daily.dev/sources/zijg9d2axrppyx4snlnev)** · [@przemyslaw91](https://daily.dev/przemyslaw91) · 7 min read · 1 upvotes · 0 comments

## Summary

Part 2 of a series on OWASP Top 10 2025 A01 (Broken Access Control) examines four common patterns where access control fails in real applications: treating authentication as authorization, trusting request parameters for identity or permission, protecting resources but not specific actions, and exposing internal references without enforcing backend permissions. Each mistake is explained with concrete examples and practical mitigation guidance. A checklist of review questions is provided to help developers and security testers audit endpoints systematically.

## Content

**Broken Access Control usually happens because the application checks the wrong thing, in the wrong place, or trusts data it should not trust.**

In Part 1, I started before the exploit.

I looked at response consistency, error messages, timing, privileged account naming, password policy, and small signals that can tell us whether an application is worth investigating further.

In Part 2, I want to move closer to the real access control failure.

But I do not want to reduce A01 to only one pattern:

```
Change the ID and access someone else’s data.
```

That is important, but Broken Access Control is wider than IDOR.

The core idea:

```
Broken Access Control happens when the application makes an authorization decision too early, too broadly, or based on data it should not trust.
```

## Mistake 1: treating authentication as authorization

![d018b600-131c-4627-8e58-031f58b05201.png](https://media.daily.dev/image/upload/s--O88-hQOf--/f_auto/v1783499350/ugc/content_aae46322-8990-445a-bb28-4291cc00ffec?_a=BAMAMicg0)

Authentication answers:

```
Who are you?
```

Authorization answers:

```
Are you allowed to do this?
```

A valid session, cookie, or token proves that the application recognised a user. It does not prove that this user can access a specific object, perform a specific action, or operate inside a specific tenant, company, team, or organisation.

A common mistake is protecting an endpoint with only a login check:

```
isAuthenticated ✅
isAllowed(user, action, resource) ❌
```

### What this means

The endpoint may be unavailable to anonymous users, but still available to any logged-in user.

A normal user is not anonymous, but they are still not automatically an administrator, owner, manager, approver, or member of every organisation.

### How to protect against it

Every sensitive request should answer four questions:

- Who is the user?
- What resource are they trying to access?
- What action are they trying to perform?
- Are they allowed to do that?

The check should not stop at “valid session”.

## Mistake 2: trusting request parameters

Another common mistake is allowing request data to define the access context.

```
{
  "userId": "user_123",
  "companyId": "company_456",
  "role": "admin",
  "ownerId": "user_123",
  "approved": true
}
```

Some of these fields may be legitimate business data in the right context.

The problem starts when the backend treats them as trusted proof of permission.

### What this means

If the user can control `userId`, `companyId`, `role`, `ownerId`, `isAdmin`, `approved`, or similar fields, they can try to move themselves into a different access context.

The request is not a trusted source of identity or permission.

The request is input.

And input can be modified.

This is risky when backend logic uses request values directly:

```
if request.companyId == target.companyId:
    allow
```

That looks like a check, but it may still be based on attacker-controlled data.

### How to protect against it

The authenticated user should come from the server-side session or validated token context, not from the request body.

```
Do not ask the request who the user is.
Derive the user from the authenticated context.
```

Then use server-side data to decide access.

Request parameters can identify what the user wants to access.

They should not prove that the user is allowed to access it.

## Mistake 3: protecting the resource, but not the action

![1fbb9076-d85b-4d06-9284-fa54c8d98dce.png](https://media.daily.dev/image/upload/s--4LYKDVve--/f_auto/v1783499420/ugc/content_3774895b-af34-4fac-a2b6-e6f944196778?_a=BAMAMicg0)

In backend frameworks, we define routes, handlers, controllers, and HTTP methods.

The problem is not that `GET`, `POST`, `PATCH`, or `DELETE` magically exist without code.

The problem is that each handler may represent a different action, and each action needs its own authorization decision.

```
GET    /api/reports/rpt_123          -> can view?
PATCH  /api/reports/rpt_123          -> can edit?
DELETE /api/reports/rpt_123          -> can delete?
POST   /api/reports/rpt_123/export   -> can export?
```

This may be the same resource, but it is not the same permission.

### What this means

A user may be allowed to view a report, but not edit it.

A user may be allowed to edit a record, but not delete it.

A user may be allowed to see data in the application, but not export it.

If the application checks only “can access this resource”, the permission may become too broad.

### How to protect against it

Use action-specific authorization:

```
can(user, "view", report)
can(user, "edit", report)
can(user, "delete", report)
can(user, "export", report)
```

Defining a route is not the same as protecting the action behind that route.

Each handler needs an authorization decision based on the user, resource, scope, and action.

## Mistake 4: exposing internal references without enforcing permission

This is more interesting than simply saying “do not hide buttons in the frontend”.

Imagine a user can access a dashboard. The dashboard contains references to pages or actions that should only be available to a more privileged user.

```
/admin/users
/admin/users/123
/admin/users/123/actions
POST /admin/users/123/delete
POST /admin/users/123/change-role
```

The link or reference itself is not always the full vulnerability.

But it gives structure.

It tells the tester where to look next.

### What this means

If the referenced page or action is still reachable without the required permission, the application has a real access control problem.

The issue is not only that the application revealed a link.

The issue is that the revealed page or action is still accessible.

This connects with Part 1.

Small signals and references can become a map. In Part 2, we follow that map and check whether authorization is actually enforced.

### How to protect against it

The backend must enforce permission on every referenced page and action.

A dashboard can guide legitimate users, but it should not become the access control layer.

A useful rule:

```
Visible reference ≠ permission
Known URL ≠ permission
Reachable route ≠ permission
```

Access control should not depend on whether the user discovered the route through the intended UI.

## Practical review questions

When reviewing an endpoint or action, I would ask:

- Is this endpoint only checking authentication?
- Is the user identity taken from trusted context or from request input?
- Does the request contain fields like `userId`, `role`, `companyId`, `ownerId`, or `isAdmin`?
- Is the application checking the specific action, not only the resource?
- Are `view`, `edit`, `delete`, `export`, `approve`, and `assign` treated as different permissions?
- Does a dashboard, API response, or client-side file reveal sensitive routes?
- If a sensitive route is known, does the backend still enforce permission?
- Would the same request fail for a different user, role, tenant, or scope?

That last question is important.

Access control is not proven only by testing the user who is allowed.

It is also proven by testing users who should be denied.

## Summary

Broken Access Control is not only about changing an ID in a URL.

It also happens when the application:

- treats login as permission,
- trusts request parameters,
- protects the resource but not the action,
- exposes internal references without enforcing permission.

A valid session, visible link, known URL, or request parameter is not proof of access.

The authorization decision belongs at the point of action.

## My takeaway

The vulnerable request matters.

But the real question is why the request was trusted.

Was the check too broad?

Was it based on user-controlled data?

Was the action protected separately?

Was the route reachable only because nobody enforced permission behind it?

That is where Broken Access Control actually happens.

In Part 3, I want to go deeper into final requests, workflows, privilege escalation, and state-changing actions.

## Extended version

This daily.dev post is a shorter technical version of the topic.

I wrote a longer Medium article where I go deeper into workflow checks, final requests, role/ownership/scope problems, and negative testing.

Read the expanded version here:

[OWASP Top 10 2025 A01: Where Broken Access Control Fails in Real Applications](https://medium.com/@cprzemek91/owasp-top-10-2025-a01-where-broken-access-control-fails-in-real-applications-f3c28b500f21)

##

---

Tags: [#security](https://daily.dev/tags/security), [#authorization](https://daily.dev/tags/authorization)

[View this post on daily.dev](https://daily.dev/posts/owasp-top-10-2025-a01-part-2-where-broken-access-control-actually-happens-nhnsckylo)
