Skip to content

Detox Technologies

BOLA and IDOR Testing for REST and GraphQL APIs

Broken Object Level Authorization, or BOLA, occurs when an API accepts an object identifier but does not verify that the current identity may access that object. IDOR is the familiar pattern: changing an ID exposes or modifies another user’s resource. The weakness can affect opaque UUIDs as easily as sequential numbers.

REST paths, GraphQL nodes, nested resolvers, batch operations, file downloads and background exports all create object-access paths. Effective testing follows ownership through the full workflow and checks reads, writes, relationships and indirect references.

Why BOLA remains a high-impact API risk

A user is often legitimately authenticated and allowed to call the endpoint, so perimeter controls see a normal request. The failure happens when the service trusts a client-supplied identifier or enforces a role without verifying ownership, tenant and current object state.

Key risk areas

1. Predictable and opaque identifiers

Sequential IDs make discovery easy, but UUIDs only reduce guessing. Identifiers are not authorization secrets and often leak in URLs, logs, notifications and related objects.

2. Nested REST resources

A route may validate the parent but not the child, or accept a child that belongs to another parent. Test every identifier independently.

3. GraphQL node and resolver access

Global IDs, aliases and nested resolvers can reach objects through multiple schema paths. Each resolver must enforce consistent policy.

4. Bulk and batch endpoints

Arrays of IDs may be authorized only once or return a mixed set. Verify each object and ensure errors do not reveal existence.

5. Files, exports and signed URLs

Downloads may use a different service or long-lived link. Test ownership, expiry, sharing and revocation after role or account changes.

6. Write and relationship operations

Changing ownership, adding members, linking objects or updating hidden fields can be more damaging than reading data.

7. Indirect object references

Names, email addresses, slugs, external IDs and cursor tokens can all select protected resources. Test every selector.

8. Caching and asynchronous jobs

A cache key or queued export that omits identity and tenant can return another user’s result after the initial request was authorized.

Step-by-step testing methodology

Step 1: Create owned test objects

For each user and tenant, create distinctive records and note relationships, sensitivity and allowed actions. Avoid touching real customer objects.

Step 2: Capture all object selectors

Review paths, query strings, JSON bodies, headers, GraphQL variables, global IDs, cursors, filenames and webhook payloads.

Step 3: Swap same-role identifiers

Replay each operation using another user’s object while keeping the authenticated identity unchanged. Test reads, edits and deletes.

Step 4: Cross tenant boundaries

Repeat with separate tenant accounts and shared roles. Check whether a client-supplied tenant header overrides authenticated membership.

Step 5: Test nested and related objects

Change parent and child IDs independently, traverse relationships and request fields resolved by downstream services.

Step 6: Exercise GraphQL features

Use aliases, fragments, node lookups, batching, mutations and subscriptions. Compare authorization across alternative resolvers.

Step 7: Test bulk and asynchronous flows

Mix authorized and unauthorized IDs, generate exports and inspect polling or download endpoints under different identities.

Step 8: Retest after lifecycle changes

Remove access, transfer ownership, disable the user and expire a share. Cached and signed resources should follow policy.

Planning a safe assessment

Use written authorisation, representative staging accounts and agreed stop conditions. Map users, service identities, data classes, APIs and third-party dependencies before testing. Separate ordinary, privileged and cross-tenant accounts, and use synthetic records that make ownership and sensitivity obvious.

Combine documentation review, configuration inspection and controlled manual testing. Automated tools help discover coverage gaps, but business authorisation and workflow weaknesses require contextual tests. Capture requests and responses, identity claims, backend decisions and downstream state changes so each result is reproducible.

Evidence, remediation and retesting

A useful finding shows the required access, exact request or build condition, affected asset and business consequence. Avoid inflating severity from a tool label. Recommend the control closest to the trusted resource, name the remediation owner and specify how the fix will be verified.

Retesting should repeat the original case and adjacent variants, including other roles, objects, endpoints and content types. Add stable regression coverage to delivery pipelines or API integration suites. Monitor production denials and anomalies to detect both attacks and policy regressions after release.

Questions to ask a testing provider

  • Will testers verify business-level authorisation and not only run scanners?
  • How are accounts, test data and potentially disruptive cases controlled?
  • Does the report include reproducible evidence, affected endpoints and remediation guidance?
  • Are fixes retested across related variants?
  • How are sensitive evidence and credentials protected and deleted?

Controls to verify

  • Ownership and tenant checks for every object at the service layer.
  • Central policy helpers used consistently across REST and GraphQL resolvers.
  • Random identifiers as defence in depth, never as the primary control.
  • Per-object authorization in bulk requests and exports.
  • Short-lived, scoped download links with revocation strategy.
  • Cache keys containing identity and authorization context.
  • Tests for relationship changes and sensitive fields.
  • Monitoring of repeated cross-object denials and enumeration patterns.

Common mistakes

  • Declaring UUIDs immune to IDOR.
  • Testing only list endpoints.
  • Checking a GraphQL query but not alternate resolvers or mutations.
  • Authorizing the parent while trusting a child ID.
  • Returning all objects then filtering in the client.
  • Forgetting files, exports, webhooks and queued results.

Related Detox resources

Start with API authentication and authorization testing and the API penetration testing service. For GraphQL-specific coverage, see the GraphQL security testing checklist.

Frequently asked questions

Does using UUIDs fix BOLA?

No. UUIDs reduce easy enumeration but do not prove permission. The server must verify access for the authenticated identity.

Is BOLA only a read vulnerability?

No. Unauthorised updates, deletes, transfers and relationship changes can have greater impact than disclosure.

How should GraphQL authorization be implemented?

Enforce policy in resolvers or the underlying business service for each object and field, independent of how the schema path was reached.

Conclusion

BOLA testing is systematic ownership testing. Inventory every selector, use controlled user and tenant pairs, cover alternative and asynchronous paths, and place authorization beside the resource so every interface receives the same decision.

Authoritative references

Building a repeatable BOLA and IDOR testing programme

BOLA and IDOR testing should be a managed capability rather than a one-time document. Define the systems in scope, accountable owners, test frequency and events that trigger reassessment. Connect results to the asset inventory, risk register and engineering workflow. Teams should agree what “complete” means: not simply that a tool finished, but that REST and GraphQL selectors, relationships, bulk operations, files and asynchronous results were exercised with valid evidence and unresolved gaps were recorded.

Create a small set of programme metrics that encourage risk reduction. Useful measures include coverage of high-value assets, percentage of tests with valid access, verified critical findings, time to remediation, recurrence and successful retest rate. Avoid rewarding raw alert volume. A rising finding count may reflect broader coverage, while a falling count may simply mean a scanner lost access.

Threat modelling and test-case design

Threat modelling makes the assessment specific to the business. Identify valuable data and actions, likely attacker positions, trust transitions and failure consequences. For bola and idor testing, give particular attention to same-role object swaps, tenant changes, nested resolvers, bulk IDs, signed downloads, cache keys and ownership transfer. Convert each threat into a positive case, a negative case and an abuse case, with expected evidence for each outcome.

Keep a traceable test catalogue. Record the requirement, precondition, identity, test data, action, expected decision and cleanup. Version the catalogue beside the architecture or service documentation. When an incident, product change or new technique appears, update the relevant cases rather than relying on individual tester memory.

Testing across the technology lifecycle

Apply lightweight checks during design and delivery, deeper validation before high-risk releases and periodic independent testing in production-like conditions. New components, permissions, providers, integrations and major configuration changes should trigger proportionate reassessment. The same control can behave differently in development and production because identity, network and data settings differ.

Coordinate with engineering and operations before testing. Establish communication channels, monitoring expectations and a rollback or stop procedure. Afterward, remove test accounts and synthetic records, revoke temporary access and confirm that evidence is retained only for the agreed period.

Prioritisation and remediation strategy

Prioritise a finding using demonstrated impact, exploitability, exposure, affected users and the reliability of compensating controls. Writes, deletes and ownership changes may carry greater business impact than a single unauthorized read. Fix systemic causes before individual symptoms: strengthen a shared policy service, identity boundary or delivery control when several findings originate from the same design weakness.

Remediation guidance should be testable. Replace vague advice such as “improve security” with the enforcement point, required behaviour and a negative test that must pass. If an immediate fix is impossible, document temporary containment, monitoring, expiry and accountable risk acceptance.

For mature APIs, include regression tests that create objects under multiple roles and tenants, then automatically replay cross-owner reads, mutations, relationship changes and downloads. Keep these tests independent of client-side controls and require the service to return a consistent denial without disclosing sensitive object details.

Discover more from Detox Technologies

Subscribe now to keep reading and get access to the full archive.

Continue reading

Verified by MonsterInsights