Detects missing ownership checks, broken role enforcement, and IDOR vulnerabilities that let users access other users' resources. Use when writing code that checks authorization, enforces resource ownership, handles IDOR (object-level authorization), processes server-side requests to external URLs, or implements access control middleware.
Protects against unauthorized resource access caused by missing ownership checks or
role enforcement. Exploitation leads to horizontal/vertical privilege escalation.
For SSRF (server-side request forgery), see the dedicated ssrf skill.
Vulnerable patterns
Resource lookup by caller-supplied identifier with no ownership predicate before the row is returned, mutated, or acted on
Privileged or admin route mounted with no role check at the route/controller declaration
Ownership check that runs after the resource has already been fetched and consumed by downstream logic
Ownership failure that responds with a distinct "forbidden" status, leaking that the resource exists
Fix immediately
Flag the vulnerable code and explain the risk. Then suggest a fix that establishes
these properties:
Every resource lookup by caller-supplied identifier is gated before the resource
is returned, mutated, or acted on. The gate binds the row to the authenticated
caller — an ownership predicate for per-instance access, or a role predicate for
role-scoped access. The check can live in a handler, interceptor, filter, annotation,
decorator, or middleware — anywhere, as long as it runs before the data is used.
Privileged routes enforce role membership through a reusable, centrally-declared
mechanism (middleware, filter chain, annotation, decorator, policy) attached at
the route or controller declaration. Ad-hoc if role != "admin" checks inside
handler bodies are brittle — they can be forgotten on a new route and they're
invisible at a glance.
Ownership failures return an indistinguishable "not found" response (HTTP 404).
Returning 403 leaks that the resource exists. Role-missing failures on a privileged
route may still return 403 — the route itself is public knowledge, so only the
instance-level check needs to hide behind 404.
Translate these principles to the audited file's language and framework. Use the
documented authorization or policy mechanism for that stack; do not invent ad-hoc
checks in handler bodies.
Verification
Confirm these properties hold (language-agnostic):
Every resource lookup by caller-supplied identifier is gated by an ownership or role predicate before the resource is returned, mutated, or acted on — regardless of whether the check lives in a handler, interceptor, filter, annotation, decorator, or middleware
Privileged routes enforce role membership through a reusable, centrally-declared mechanism (middleware, filter chain, annotation, decorator, policy) attached at the route/controller declaration — not via ad-hoc if checks inside individual handler bodies
Ownership (per-instance IDOR) failures return an indistinguishable "not found" response (e.g. HTTP 404) rather than a distinct "forbidden" response, to prevent resource enumeration. Role-missing failures on a privileged route may use 403 because the route itself is public knowledge
1---2name: broken-access-control3description: Detects missing ownership checks, broken role enforcement, and IDOR vulnerabilities that let users access other users' resources. Use when writing code that checks authorization, enforces resource ownership, handles IDOR (object-level authorization), processes server-side requests to external URLs, or implements access control middleware.4---56# Broken Access Control Security Check (A01:2025)78## What this checks910Protects against unauthorized resource access caused by missing ownership checks or11role enforcement. Exploitation leads to horizontal/vertical privilege escalation.12For SSRF (server-side request forgery), see the dedicated `ssrf` skill.1314## Vulnerable patterns1516- Resource lookup by caller-supplied identifier with no ownership predicate before the row is returned, mutated, or acted on17- Privileged or admin route mounted with no role check at the route/controller declaration18- Ownership check that runs after the resource has already been fetched and consumed by downstream logic19- Ownership failure that responds with a distinct "forbidden" status, leaking that the resource exists2021## Fix immediately2223Flag the vulnerable code and explain the risk. Then suggest a fix that establishes24these properties:25261. **Every resource lookup by caller-supplied identifier is gated before the resource27 is returned, mutated, or acted on.** The gate binds the row to the authenticated28 caller — an ownership predicate for per-instance access, or a role predicate for29 role-scoped access. The check can live in a handler, interceptor, filter, annotation,30 decorator, or middleware — anywhere, as long as it runs before the data is used.312. **Privileged routes enforce role membership through a reusable, centrally-declared32 mechanism** (middleware, filter chain, annotation, decorator, policy) attached at33 the route or controller declaration. Ad-hoc `if role != "admin"` checks inside34 handler bodies are brittle — they can be forgotten on a new route and they're35 invisible at a glance.363. **Ownership failures return an indistinguishable "not found" response (HTTP 404).**37 Returning 403 leaks that the resource exists. Role-missing failures on a privileged38 route may still return 403 — the route itself is public knowledge, so only the39 *instance-level* check needs to hide behind 404.4041Translate these principles to the audited file's language and framework. Use the42documented authorization or policy mechanism for that stack; do not invent ad-hoc43checks in handler bodies.4445## Verification4647Confirm these properties hold (language-agnostic):4849- [ ] Every resource lookup by caller-supplied identifier is gated by an ownership or role predicate before the resource is returned, mutated, or acted on — regardless of whether the check lives in a handler, interceptor, filter, annotation, decorator, or middleware50- [ ] Privileged routes enforce role membership through a reusable, centrally-declared mechanism (middleware, filter chain, annotation, decorator, policy) attached at the route/controller declaration — not via ad-hoc `if` checks inside individual handler bodies51- [ ] Ownership (per-instance IDOR) failures return an indistinguishable "not found" response (e.g. HTTP 404) rather than a distinct "forbidden" response, to prevent resource enumeration. Role-missing failures on a privileged route may use 403 because the route itself is public knowledge5253## References5455- CWE-284 ([Improper Access Control](https://cwe.mitre.org/data/definitions/284.html))56- CWE-862 ([Missing Authorization](https://cwe.mitre.org/data/definitions/862.html))57- CWE-863 ([Incorrect Authorization](https://cwe.mitre.org/data/definitions/863.html))58- CWE-918 ([Server-Side Request Forgery](https://cwe.mitre.org/data/definitions/918.html))59- [OWASP A01:2025 Broken Access Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/)
Run npx skillmds@latest add thejefflarson/broken-access-control in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Detects missing ownership checks, broken role enforcement, and IDOR vulnerabilities that let users access other users' resources. Use when writing code that checks authorization, enforces resource ownership, handles IDOR (object-level authorization), processes server-side requests to external URLs, or implements access control middleware. It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
thejefflarson (@thejefflarson) published this skill. Their other Agent Skills are listed on their SkillMD profile.