Join our Newsletter — 33% off our NHI Course
Home› Guides› Authorisation Testing Automation Guide: Regression Tests for Access…
Guide Web & API Security

Authorisation Testing Automation Guide: Regression Tests for Access Control

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 27 October 2026 14 min read
On this page

Broken access control is rarely a design failure that a one-off penetration test catches and fixes; it is a regression that returns every time a developer adds an endpoint, a field or a tenant feature without the check. Broken object level authorisation (BOLA), broken function level authorisation (BFLA) and broken object property level authorisation (BOPLA) are API1, API5 and API3 in the OWASP API Security Top 10 2023, and they are found by attackers at scale because they are cheap to probe. The durable fix is to turn the access rules into an executable specification and test every release against it. This guide explains how to build that: an authorisation matrix as the test oracle, policy unit tests, multi-user integration tests, role-replay dynamic scanning, CI gates, test identities and the metrics that prove coverage. It is for application security engineers, QA and platform teams; the wider API programme is in the API Security Guide.

Key takeaways

  • Write the rules down first. The OWASP Authorization Testing Automation Cheat Sheet starts with a machine-readable authorisation matrix of roles, endpoints and expected outcomes; without it, tests encode whatever the code currently does.
  • Test denial, not just access. Most functional tests prove the right user can do something; authorisation tests must prove every other user cannot, including users in another tenant.
  • Two users and two tenants catch most BOLA. Fixtures with user A and user B owning separate objects, and the same pair in a second tenant, turn ownership checks into simple assertions.
  • Layer the tests. Policy unit tests, matrix-driven integration tests, and role-replay dynamic scans each catch different failures; none replaces skilled manual testing, as the OWASP Authorization Cheat Sheet notes.
  • Make it a release gate. OWASP API1 guidance is direct: write tests for the authorisation mechanism and do not deploy changes that make them fail.

Why access control regresses

Authorisation logic is spread across controllers, middleware, data access filters, gateway policies and front ends, and it changes whenever the product does. Typical regressions are mundane:

  • A new endpoint without the decorator: a developer copies a handler and forgets the policy, or a framework's default is anonymous.
  • A new route to an old object: a v2 endpoint, export feature or GraphQL resolver that loads records by ID without the ownership filter used by v1.
  • A new field: the response serialiser now returns role, discount or another tenant's identifier, or the update handler binds it from input (mass assignment, BOPLA).
  • A new method: GET is checked but PUT, PATCH or DELETE on the same path is not, or a method override header bypasses the route rule.
  • A new tenant model: the check validates the user's role but not that the object belongs to the user's organisation.

The common thread is that the code compiles, functional tests pass and the feature works for the user who built it. Only a test that asks "what happens when someone else tries this" fails. The Broken Access Control Prevention Guide covers how to design the checks; this guide covers how to keep them.

The authorisation matrix as the test oracle

The OWASP cheat sheet formalises access rules in a matrix file with three parts: the roles, the services (URI, HTTP method, the response expected when access is allowed and when it is denied, and which roles are allowed), and test payloads for services that need a request body. Integration tests read the matrix as their only input, call every service as every role, and compare actual with expected status codes; failures name the service, the point of view (role), the actual and the expected result. The matrix can be rendered for auditors and business owners, so the rules are reviewed by people who understand them.

The cheat sheet's sample is deliberately minimal: it checks status codes only and uses a fixed object ID, so it does not test per-object ownership. Production matrices need three more dimensions:

DimensionExample ruleWhat it catches
Function (role or permission)DELETE /invoices/{id} allowed for finance_admin onlyBFLA, privilege escalation
Object relationshipGET /invoices/{id} allowed if owner or same org with viewerBOLA, insecure direct object references
Tenant boundaryNo role grants access to an object in another tenant, except support with an active ticketCross-tenant leakage
Property (read and write)user may read but not write credit_limit; may not read internal_notesBOPLA, mass assignment, excessive data exposure
Expected denial response403 for authenticated non-owners, 404 where existence must not leak, 401 without identityInconsistent errors that confirm object existence

Store the matrix in the repository as YAML or JSON next to the code, require security or product owner review for changes, and generate it from your OpenAPI description where possible so new endpoints appear in the matrix automatically, initially marked "deny all" until someone writes the rule. ASVS 5.0 V8.1.1 expects exactly this kind of documentation of function-level and data-specific rules.

Test layers and what each catches

LayerTypical toolingCatchesMissesRuns
Policy unit testsopa test for Rego, Cedar or OpenFGA test suites, framework handler testsLogic errors in the decision function, edge cases in attributesEndpoints that never call the policyEvery commit, seconds
Matrix-driven integration testsTest framework plus HTTP client, matrix file, seeded fixturesMissing checks on endpoints, method gaps, cross-user and cross-tenant accessEndpoints absent from the matrixEvery merge, minutes
Property and schema testsResponse schema validation, field allowlists per roleBOPLA, fields leaking after serialiser changesLogic flaws in business flowsEvery merge
Role-replay dynamic scanningZAP Access Control Testing add-on, Burp Suite Autorize extensionEndpoints reached in the running app that tests forgot, including front-end callsPaths the crawl or browsing session never reachedNightly or pre-release
Manual and exploratory testingPenetration testers using the OWASP Web Security Testing Guide authorisation testsMulti-step and business logic bypassesRegressions between testsPer major release
Production monitoringAuthorisation decision logs, anomaly alertsLive probing and exploitationNothing before releaseContinuously
  • Policy tests: OPA runs every rule prefixed test_, mocks input and data with the with keyword, reports line coverage with --coverage, and fails an empty run with --fail-on-empty, which stops a renamed file silently disabling the suite in CI. Data-driven cases loaded from JSON or YAML let the same matrix feed policy tests and integration tests.
  • ZAP: the Access Control Testing add-on defines users and contexts, marks each URL Allowed, Denied or Unknown per user (rules inherit down the URL tree), attacks every URL as every user and raises alerts 10101 (Improper Authentication) and 10102 (Improper Authorization). See the OWASP ZAP Guide.
  • Autorize: the Burp Suite extension replays every request a high-privilege tester makes with a low-privilege user's cookies or headers and without credentials, and labels results bypassed, enforced or uncertain, with configurable enforcement detectors. It is excellent for exploratory sessions and for building the first matrix. See the Burp Suite for Authorised Web Testing Guide.
  • Manual testing: the OWASP Web Security Testing Guide v4.2 groups authorisation tests as directory traversal and file include, bypassing the authorisation schema, privilege escalation and insecure direct object references. Use automation to keep testers' time for chained and business-logic attacks.

Designing tests that catch BOLA, BFLA and BOPLA

Fixtures

  • Two users, two tenants: seed tenant T1 with users A (owner) and B (same role, different objects), plus a privileged user P; seed tenant T2 with user C. Every object-level test runs as A (expect allow), B (expect deny), C (expect deny, and the same response as for a non-existent ID) and anonymous (expect 401).
  • Realistic identifiers: test with the identifier types attackers use: sequential integers, UUIDs taken from another tenant's responses, IDs in path, query, body, headers and GraphQL variables. Random UUIDs reduce guessing but are not access control; the OWASP Authorization Cheat Sheet says obscuring IDs alone is not sufficient.
  • All methods: for each path, test every method the router accepts, including HEAD, OPTIONS and method override headers.

Assertions

  • Status and body: do not stop at the status code. A 200 with an empty list may be correct; a 200 with another user's record is a failure; a 403 for a non-owner and 404 for a non-existent ID can confirm existence. Assert on body content for denials.
  • Side effects: for writes, assert that the object did not change after a denied request; some handlers return 403 after the update has already committed.
  • Properties: for each role, assert the exact set of fields returned (an allowlist), and send updates containing fields the role must not change (role, tenant_id, price) and assert they were ignored or rejected. This is ASVS 5.0 V8.2.3 in test form.
  • Lists and search: collection endpoints, exports and search must filter by tenant and permission; assert that B's search never returns A's records.
  • Freshness: remove a role and assert denial within the documented window (ASVS V8.3.2 expects changes to authorisation inputs to apply immediately or within a bounded time).

Building it into the pipeline

  1. Bootstrap the matrix: export routes from the framework or OpenAPI description; run an Autorize or ZAP session against staging with each role to record current behaviour; review the result with product owners and mark each cell as intended or a defect.
  2. Start in report-only mode: run matrix tests on every merge but do not block; triage failures for two to four weeks until false positives are gone and true defects are ticketed.
  3. Gate new endpoints first: fail the build when an endpoint exists in code but not in the matrix, or exists in the matrix as "deny all" and returns success. This stops the backlog growing while old defects are fixed.
  4. Gate regressions: once green, any cell that changes from deny to allow fails the build unless the matrix change was approved in the same pull request.
  5. Add the dynamic layer: schedule ZAP or equivalent role-replay scans against a production-like environment nightly, and compare results with the matrix.
  6. Roll back safely: because the matrix is versioned with the code, reverting a release reverts the expected rules too; keep a manual override for emergency releases that requires a named approver and a follow-up ticket.

Decision guidance: small teams with one API should start with matrix-driven integration tests in their existing test framework and an occasional Autorize session; that alone catches most BOLA and BFLA. Larger organisations with many services gain from externalised authorisation (a policy engine or authorisation service) because one policy test suite then covers many applications; see the Externalised Authorisation Buyer's Guide and the Authorisation Models Guide. Multi-tenant SaaS should treat cross-tenant tests as non-negotiable from day one.

Test identities and test data

Authorisation tests need real credentials for several users in several tenants, which makes the test suite itself a set of non-human identities to govern.

  • Dedicated test identities: create test users per role and tenant in a non-production identity provider tenant; never reuse real staff accounts or production service tokens.
  • Short-lived tokens: have the pipeline obtain tokens at run time (for example via a test-only client using client credentials or a token exchange) rather than storing long-lived bearer tokens in CI variables. See the CI/CD Pipeline Identity Security Guide.
  • No test back doors in production: test-only sign-in routes, headers that set the user ID, or disabled token validation must not exist outside the isolated test environment.
  • Synthetic data: seed fixtures with synthetic records so failures that dump data in CI logs expose nothing real.

Detection and measurement

Tests prevent regressions; logs catch what tests miss. ASVS 5.0 V16.3.2 requires failed authorisation attempts to be logged. Alert on one identity receiving many 403 or 404 responses across sequential or varied object IDs, on cross-tenant access attempts, and on unusual volumes from a single token, which is how bulk BOLA exploitation looks in practice.

Metrics:

  • Matrix coverage: percentage of routes and methods in the matrix (target 100 percent, with new routes defaulting to deny).
  • Negative test ratio: denial assertions per allow assertion; healthy suites have several denials per allowed path.
  • Cross-tenant coverage: percentage of object endpoints with a cross-tenant test.
  • Escape rate: access control findings from penetration tests, bug bounty and incidents that the automated suite did not catch, tracked per quarter and fed back as new tests.
  • Mean time to fix for authorisation failures blocked in CI against those found in production.

Framework mapping

PracticeNIST SP 800-53 Rev. 5NIST CSF 2.0OWASP ASVS 5.0OWASP API Top 10 2023
Documented authorisation matrixAC-3, AC-24PR.PS-06V8.1.1API1, API5
Function-level regression testsSA-11, AC-6PR.PS-06V8.2.1API5
Object-level and cross-tenant testsSA-11, AC-3PR.PS-06V8.2.2API1
Property-level testsSA-11PR.PS-06V8.2.3API3
Server-side enforcement checksAC-3PR.PS-06V8.3.1API5
Dynamic scanning and penetration testingRA-5, CA-8ID.RA-01, ID.IM-02n/aAll
Logging of failed authorisationAU-2PR.PS-04V16.3.2API1

Unchecked object access is usually exploited through ordinary authenticated sessions, which ATT&CK records under T1190 Exploit Public-Facing Application, often with T1078 Valid Accounts.

Common failure patterns

  • Testing only the happy path: suites prove the owner can read their invoice and never try as anyone else.
  • One user per role: without a second user of the same role, ownership checks are never exercised, so role-based tests pass while BOLA remains.
  • Status code only: a denial test passes on 403 even though the write was committed before the error, or a 200 hides another tenant's data in the body.
  • The matrix drifts: new endpoints are added to code but not to the matrix, so the gate never sees them; make "missing from matrix" a failure.
  • Scanner configured once: a dynamic scan with expired test sessions reports everything as enforced because every request now returns 401.
  • Admin APIs out of scope: internal and support tooling is excluded from tests, yet it often holds the broadest access.

Lessons from incidents

The McHire Default Password Flaw 2025 combined two failures that automated tests are built for. An internal API fetched applicant records by a sequential ID, so changing the number returned other applicants' details, with researchers estimating more than 64 million records reachable; and a dormant test account with the default credentials 123456 gave the researchers administrator access to start from. A two-user test on the record endpoint and a check that test accounts cannot exist in production would each have stopped it. See also the OWASP API Top 10 API1 Broken Object Level Authorization Guide.

Practitioner checklist

  • Write an authorisation matrix covering role, object relationship, tenant and property rules, versioned with the code.
  • Default new routes to "deny all" in the matrix and fail the build for routes missing from it.
  • Seed two users per role and two tenants, and run every object test as owner, peer, other tenant and anonymous.
  • Test every HTTP method and identifier location, not just the obvious one.
  • Assert on bodies and side effects, not only status codes.
  • Add field allowlists per role and mass-assignment tests.
  • Unit test policy code with coverage and --fail-on-empty (or the equivalent).
  • Schedule role-replay dynamic scans and keep their test sessions valid.
  • Govern test identities as NHIs: non-production tenant, short-lived tokens, no test back doors in production.
  • Log failed authorisation, alert on enumeration patterns, and feed every escaped finding back as a new test.

Standards and references

Related NHI Mgmt Group resources: API Security Guide · OWASP API Top 10 API5 Broken Function Level Authorization Guide · OWASP API Top 10 API3 Broken Object Property Level Authorization Guide · API Penetration Testing Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 27 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org