Enterprise App Security: Why Hidden URLs Are Not Access Control

Enterprise app security needs access checks that still work when someone knows the URL and sends the request without using the interface. OWASP's guidance on broken access control identifies modified URLs and API requests as ways to bypass inadequate controls, and places effective enforcement in trusted server-side code.
For an internal application, we recommend starting with a specific question: can a signed-in user read or change a record they do not own? Test that question against the API, not only against the screens the user normally sees. A permission rule should describe the permitted action on the particular record, with a test showing that the server refuses everything outside it.
A hidden button is a presentation choice
Removing a delete button tells the interface what to display. It does not demonstrate that the server rejects a delete request. OWASP explicitly includes missing access controls on POST, PUT and DELETE requests among its examples of broken access control.
Consider a hypothetical inspection application. An inspector may edit draft observations for an assigned site, while a supervisor may approve the finished inspection. We would write those permissions before deciding which buttons to show. The interface should then reflect the same rules, rather than become the only place those rules exist.
For that example, test a direct approval request made with the inspector's account. Require the server to refuse it, even when the request has the same shape as a supervisor's request. Also require the failed attempt to leave the inspection unchanged. These are proposed acceptance criteria, not a claim about a particular product.
Knowing who someone is does not settle what they may do
Saltzer and Schroeder's security design paper distinguishes authenticating an identity from checking authority over an object. Its complete mediation principle requires an authority check for every access to every object.
Apply that distinction to an enterprise workflow. We recommend treating a role such as inspector as one input to the decision, alongside the record's organisation, assignment and current state. Write down the combinations the business permits. Do not assume that a successful sign-in grants permission to edit every inspection.
For the hypothetical application, a useful rule would be: an inspector may edit an assigned inspection belonging to their organisation while it remains a draft. A supervisor's approval permission should be a separate rule. Product owners should confirm these choices before engineers implement them, because they describe the business process rather than a framework default.
Make the failure cases explicit too. What should happen when the inspection has already been approved? What should happen when the user's site assignment changes? We recommend recording the expected refusal alongside the allowed case so the implementation has an answer for both.
Check the record, not only the route
OWASP describes access to another person's account through its identifier as an access-control failure and recommends enforcing record ownership. Protecting an administrative route and checking access to an individual record are therefore separate review questions.
In our proposed test, create fixtures for two organisations. Give an inspector permission over a draft inspection in the first, then submit the second organisation's inspection identifier using that inspector's account. Require refusal without returning the second organisation's inspection content. Repeat the check for an attempted update, and verify that the stored record did not change.
Treat those fixtures as part of the permission specification. Record which identity made the request, which record it targeted and what outcome was expected. Keep a successful request in the same test group so a blanket refusal cannot satisfy the whole specification.
We also recommend reviewing exports and attachment downloads against the same record rules. List each access path in the review rather than assuming a check on the main editing screen proves the others. This is a review method, not a guarantee that any one application exposes those paths.
Deny access before deciding what to reveal
A hidden resource and an unprotected resource are different things. HTTP Semantics, RFC 9110, permits a server to answer with 404 instead of 403 when it wishes to conceal the existence of a forbidden resource. That is a response choice after the server refuses access, not a replacement for the refusal.
For a confidential inspection, we recommend agreeing both outcomes in advance: the server must not release the record, and the response must not disclose more than the policy permits. Test the response body as well as the status code. Do not call a test successful merely because the browser displays an error page.
The older open design principle makes the underlying distinction clear: protection mechanisms should not depend on an attacker's ignorance of their design. Keeping credentials secret is compatible with having a design that engineers can inspect and challenge.
Make permission tests part of delivery
OWASP recommends access-control unit and integration tests. We would make the agreed permission examples release criteria, with an owner responsible for updating them when the business rules change.
Start with one sensitive action, such as approval or deletion. Write its allowed case and its refusal cases, exercise them through the server and inspect the resulting data. Ask a reviewer who did not implement the rule to compare those tests with the written permission. Expand from that example to the remaining sensitive actions, keeping the evidence with each change.
Update, October 2026
For teams introducing agents into delivery, we recommend giving the agent the same permission specification and requiring the same refusal tests. Our engineering article on gated build loops and independent review describes a delivery process with separate review and real-system verification. Apply that review discipline to access-control changes, with the business permission and the server's refusal evidence in the review brief.
Sources
- Saltzer and Schroeder, "The Protection of Information in Computer Systems: Basic Principles", manuscript revised 17 April 1975.
- OWASP, "A01:2021: Broken Access Control", pinned repository revision, 12 July 2025.
- IETF, "RFC 9110: HTTP Semantics", 6 June 2022.
Want this in your team?
Tell us what you're building and where you want to get to, and we'll think it through with you.