Safeguard
Product•

Testing APIs for BOLA, IDOR, auth and data exposure, and where Safeguard fits

How to test APIs for BOLA, IDOR, broken auth and data exposure on targets you own, and where Safeguard's API Security integration fits that job.

Safeguard Security Team
39 min read

To test an API for broken object level authorization (BOLA, often called IDOR), broken authentication and excessive data exposure, you need three things: a complete list of the endpoints, at least two test identities that should not see each other's data, and a written expectation for every endpoint about who may read or change which object. Automated dynamic testing gives you the inventory, the authenticated requests and the transport level findings; the question "should user A be able to read order 1234?" is a business rule that only your team can answer. Run all of it only against systems you own or are explicitly authorized to test.

This post walks through what the OWASP API Security Top 10 2023 means by each of these risks, a test plan you can run this week with whatever tools you have, and then how Safeguard's API Security integration (GA) fits: it runs authenticated API testing for BOLA and IDOR, authentication and data exposure against targets you have verified, reads your collection or spec, signs requests with a test account, and puts the results next to your static analysis findings.

Key takeaways

  • BOLA (API1:2023) is the most common way APIs leak other people's data. The server trusts an object identifier from the client without checking that the caller may use that object. IDOR is the older web name for the same flaw.
  • Broken authentication (API2:2023) and broken object property level authorization (API3:2023, which merged "excessive data exposure" and "mass assignment") usually travel with BOLA. Test them together.
  • Authorization flaws are business logic. A scanner can send the request; only your access rules can say whether the 200 response was allowed. Plan for two or more test identities and an access matrix.
  • Safeguard API Security integration (GA) runs authenticated API testing for BOLA and IDOR, authentication and data exposure. It tests an API from a live URL, an OpenAPI or Swagger file, a pasted curl command or a Postman collection, and only after you verify ownership of the target.
  • Safeguard DAST (GA) runs with enforced scope, rate limits, non-destructive checks and safety modes (passive, safe_active, authenticated_safe_active), with a full audit trail.
  • Safeguard SAST (GA) findings share one model with DAST and SCA findings, so a runtime issue can be linked to the source to sink path that produced it.
  • Policies and gates (GA) act on findings with Block, Warn and Notify; approval for a known exception runs through exceptions.
  • The Safeguard CLI (GA) and local runner (GA) let you run the same scans in CI or inside your own network for private hosts. The Safeguard MCP server (GA) lets an assistant such as Claude read the results.

The situation

The trigger is usually one of three things. A partner or customer security questionnaire asks how you test your public API for authorization flaws. A penetration test report lands with a finding that one customer could read another customer's invoice by changing a number in the URL. Or your team ships a mobile app or a partner API and someone in the launch review asks, reasonably, "who checked that the new endpoints enforce tenancy?"

The person on the hook is typically the head of application security or product security, with the API's owning engineering team doing the fixes. The deadline is the release, the questionnaire due date or the retest window in the pentest statement of work.

A bad week looks like this. The pentest finding is real, but nobody knows how many other endpoints share the same pattern because there is no endpoint inventory. The OpenAPI file is a year old. The Postman collection the QA team uses has a login script that stores a token, so nobody outside QA can replay it. The test accounts all belong to the same tenant, so cross-tenant access cannot be tested at all. And the scanner that runs nightly reports missing headers but says nothing about whether tenant A can read tenant B's records, because it was never told that tenant B exists.

The rest of this post is about getting out of that week with a repeatable process.

What the OWASP API Security Top 10 2023 says

The OWASP API Security Top 10 is the reference list most questionnaires and pentest reports point at. The 2023 edition is the current one. Four of its entries describe the problems in this post's title, and a fifth explains why they hide so well.

API1:2023 Broken Object Level Authorization

OWASP explains that APIs tend to expose endpoints that handle object identifiers, and every one of those endpoints is a place where an object level access check can be missing. The pattern: an endpoint accepts an identifier for a record (an order, an invoice, a patient record, a document) in the path, the query string, a header or the body, and the server returns or changes that record without checking that the authenticated caller is allowed to use it.

The OWASP page is explicit that the check must happen in every function that accesses a data source using an input from the user. Comparing the user ID from the session with a user ID in the request is not enough on its own, because the object being requested is the thing that needs the check, not the user parameter.

Why it is so common: frameworks make authentication easy to add globally (a middleware that rejects requests without a valid token), but object level authorization is specific to each data model and each query. It has to be written, and tested, endpoint by endpoint.

Is IDOR the same as BOLA?

Mostly, yes. Insecure Direct Object Reference is the older term from web application testing, and the OWASP Web Security Testing Guide still has a test case for it under authorization testing. BOLA is the API focused name the API Security project uses. The flaw is the same: a reference to an internal object is exposed to the client, and the server does not verify that the caller may use the referenced object. For a deeper primer on each, see what is broken object level authorization and what is an insecure direct object reference.

One practical difference: in API work the identifier is often not in the URL at all. It can sit inside a JSON body, a GraphQL argument or a header such as a tenant or account ID. Tests that only change path parameters miss those.

API2:2023 Broken Authentication

OWASP's API2 covers weaknesses in how an API identifies its caller: endpoints that should require authentication but do not, tokens that are accepted after they should have expired, weak or missing validation of token signatures and claims, credentials sent in URLs, and missing protections on login, password reset and token refresh flows. The authentication layer is what every authorization check depends on. If the API can be convinced that a request comes from a different user, every object level check after it is checking the wrong person.

API3:2023 Broken Object Property Level Authorization

The 2023 edition merged two entries from the 2019 list: "excessive data exposure" and "mass assignment". The common root is that authorization is checked for the object but not for the individual properties of the object.

On the read side, the API returns more fields than the caller should see (an internal flag, another user's email, a cost price) and relies on the client to hide them. On the write side, the API binds every field in a request body onto the model, so a caller can set properties they should never control, such as a role, a price, an owner or an approval status.

This is the data exposure part of this post's title. It is easy to miss in testing because the response is a normal 200 with a normal looking body. You only see the problem if you know which fields a given role should receive.

API5:2023 Broken Function Level Authorization

BFLA is the vertical sibling of BOLA. Instead of reaching another user's object, a regular user reaches a function meant for another role: an admin endpoint, an export, a bulk delete, a role change. OWASP notes that administrative functions are often exposed under predictable paths and protected only by the client not showing the button. Test it with the same access matrix you build for BOLA, adding a role axis.

API9:2023 Improper Inventory Management

API9 is not an authorization flaw, but it is why authorization flaws survive. Old API versions, undocumented endpoints, staging hosts that point at production data and forgotten partner endpoints all carry the access control logic of whenever they were last touched. You cannot test what you have not listed. Every plan below starts with inventory for that reason. For the full list with examples, see the OWASP API Security Top 10 explained.

Other rules and guidance that point at the same flaws

The OWASP list is a risk ranking, not a control standard. When a questionnaire or an auditor asks "how do you test for this?", these are the documents that usually sit behind the question. This is not legal or audit advice; read the primary text for the version your contract or assessor names.

  • CISA, NSA and the Australian Cyber Security Centre, joint advisory AA23-208A (27 July 2023). The advisory, titled "Preventing Web Application Access Control Abuse", is about IDOR specifically. It asks vendors and developers to build secure by design and by default, to deny access by default, and to perform authentication and authorization checks for every request that modifies, deletes or accesses sensitive data. It recommends automated code analysis tools, points developers to NIST's SSDF, and suggests considering dynamic application security testing (DAST) tools to find IDOR in web applications. It also suggests replacing exposed identifiers with random values such as UUIDs, while noting that UUIDs should not be used as a security capability.
  • OWASP Application Security Verification Standard (ASVS). ASVS is the control standard that turns the risk list into testable requirements; version 5.0.0 is the current stable release. Its authorization requirements ask that access controls are enforced at a trusted service layer, that users can only access data and functions they are authorized for, and that object level checks protect against IDOR.
  • OWASP Web Security Testing Guide (WSTG). The authorization testing section includes a test case for insecure direct object references, and the authentication section covers the login, session and recovery tests that API2 refers to.
  • NIST SP 800-218, the Secure Software Development Framework (February 2022). Practice PW.8 is "Test Executable Code to Identify Vulnerabilities and Verify Compliance with Security Requirements", and PW.7 covers review and analysis of human-readable code. For an API, authorization testing against written access requirements is a direct way to meet PW.8, and task PW.8.2 asks you to scope the testing and design the tests.
  • NIST SP 800-228, Guidelines for API Protection for Cloud-Native Systems (final, June 2025). NIST's API specific guidance covers API inventory, authentication and authorization at each request, and the controls to apply before and during runtime.

None of these names a specific tool. All of them expect you to be able to show that authorization is enforced on every request and that you test it.

Why scanners struggle with authorization flaws

It helps to be clear about this before you buy or configure anything, because it shapes what "covered" means.

A dynamic scanner is very good at questions where the answer is visible in a single response. Is a security header missing? Does a malformed input produce an error that reveals a stack trace? Does the server accept a request with no token at all? Those questions have one right answer for every API.

Authorization questions do not. When user A requests order 1234 and gets a 200, the scanner cannot know whether order 1234 belongs to user A. It might be A's own order. It might be a public catalogue item. It might be tenant B's confidential invoice. The difference lives in your data model and your business rules.

So authorization testing needs inputs that a scanner cannot infer:

  1. Identities. At least two users in different tenants, plus a user in each role that matters (reader, editor, admin, support).
  2. Ownership facts. Which objects belong to which identity, so a test knows that A requesting B's object should fail.
  3. Expected outcomes. For each endpoint and identity pair, the response that is correct: a 403, a 404 that does not confirm existence, or a filtered result.

Tools can carry these inputs and replay them consistently. They cannot invent them. That is consistent with the CISA advisory, which treats DAST as one input to IDOR testing alongside code review, fuzzing and penetration testing, not as a replacement for them. Any vendor or plan that claims to find all BOLA flaws with no identities and no ownership facts is skipping this step.

Step by step: an authorization test plan you can run this week

This plan works with any HTTP client, a test framework your developers already use, and the API description you already have. It is defensive by design: it uses test accounts on systems you own, and it never touches real customer data.

1. Build the endpoint inventory

Start from every source you have and merge them: the OpenAPI or Swagger file, the Postman collections your QA and partner teams use, API gateway route tables, and the routes your framework registers at startup. Mark each endpoint with:

  • the HTTP method and path
  • every place it accepts an object identifier (path, query, header, body, GraphQL argument)
  • whether it reads, creates, changes or deletes
  • the roles that should be able to call it
  • whether it is public, partner, internal or deprecated

Endpoints that appear in one source but not another are your first findings. A route registered in code but missing from the spec is exactly the kind of shadow endpoint API9 warns about.

2. Confirm you are authorized to test each host

Write down which hosts are in scope, who owns them and who approved the test. Remove anything you do not own: payment providers, identity providers, email and messaging services, and any partner API your collection happens to call. Testing someone else's API, even by accident, is not defensive work. If the API runs only inside your network, plan to test it from inside your network.

3. Create test identities and seed test data

Create at least:

  • two users in tenant A with different roles (for example a reader and an admin)
  • one user in tenant B
  • one service or partner credential if the API has machine callers

Seed each tenant with a small set of objects of every type the API serves, and record their identifiers. Use a dedicated test environment where possible. If you must test in production, use test tenants that hold no real customer data, and agree the window with operations.

4. Write the access matrix

The access matrix is the single most useful artifact in authorization testing. Rows are endpoint and object pairs; columns are identities; each cell is the expected outcome. Here is a template you can copy into a spreadsheet:

EndpointObjectOwnerTenant A readerTenant A adminTenant B userNo token
GET order by IDOrder A-1Tenant AAllowAllowDeny (404)Deny (401)
PATCH order by IDOrder A-1Tenant ADeny (403)AllowDeny (404)Deny (401)
GET invoice PDFInvoice A-7Tenant AAllowAllowDeny (404)Deny (401)
POST user role changeUser A-2Tenant ADeny (403)AllowDeny (404)Deny (401)
GET admin exportn/an/aDeny (403)AllowDeny (403)Deny (401)

Decide as a team whether cross-tenant denials return 403 or 404. Many APIs return 404 so the response does not confirm that the object exists; whichever you pick, be consistent, because inconsistency is itself an information leak.

5. Run the paired tests

For each row, send the request as each identity and compare the actual outcome with the expected one. The pattern is always the same: a request that is allowed for the owner is repeated, unchanged except for the credential, by an identity that should not have access. Any "Allow" where the matrix says "Deny" is a finding.

Do this for every place the identifier appears. If an endpoint takes an account ID in a header and an order ID in the path, test changing each one on its own and both together.

Keep the tests non-destructive. For write endpoints, use objects created for the test, and prefer requests that a successful check would reject before any change happens. You are confirming that the check exists, not seeing how much damage a missing check can do.

6. Check what comes back, not only the status code

For every allowed request, compare the response body with what that role should see. A simple way is to keep, per endpoint and role, an allow-list of fields. Anything outside the list is a property level finding under API3. Look in particular for:

  • identifiers or contact details of other users
  • internal flags, cost fields, risk scores or notes
  • fields that exist only for admins
  • nested objects that pull in a related record from another tenant

For write endpoints, send the documented body plus one field the role should not control (for example a status or owner field set to a harmless test value) and confirm the server ignores or rejects it.

7. Run the authentication checklist

Work through these for every authenticated endpoint, again with test accounts only:

  • request with no credential returns 401
  • request with an expired token returns 401
  • request with a token issued for a different audience or environment is rejected
  • request with a token whose signature does not validate is rejected
  • logout and password change invalidate existing sessions or tokens as your design intends
  • password reset and login endpoints are rate limited and do not reveal whether an account exists
  • credentials never appear in URLs, logs or error messages

8. Fix at the source, then retest

Every finding goes to the owning team with the matrix row that failed. The fix belongs in the code, usually in one of the places described in the next section. When the fix ships, rerun the same row with the same identities. Keep the matrix under version control next to the API so the next endpoint added gets a row before it ships.

A one page decision table

QuestionIf yesIf no
Do you have a current list of every endpoint and host?Go to identitiesBuild the inventory first (API9)
Do you own or have written approval for every host in scope?ProceedRemove the host or get approval
Do you have identities in at least two tenants?Test BOLA cross-tenantYou can only test same-tenant and role checks
Do you have a role axis in the matrix?Test BFLAAdd roles before release
Do you know which fields each role should see?Test API3 data exposureWrite the field allow-lists
Can the test run without a login script?Automate it in CIMove tokens into an environment for test accounts

Where each flaw gets fixed

Testing finds the gap; these are the fixes your engineers usually reach for. None of them is new, and none needs a particular product.

  • Object level checks in the data access path. Put the ownership check where the query happens, for example by scoping every query to the caller's tenant and user, rather than in a controller that a new endpoint can forget. Deny by default.
  • One authorization helper, used everywhere. A shared policy function that takes the caller, the action and the object is easier to review and test than checks copied into every handler.
  • Unpredictable identifiers are not authorization. Random UUIDs make enumeration harder, and the CISA advisory suggests them, while also noting that UUIDs should not be used as a security capability. They leak through logs, referrer headers, shared links and other endpoints. The check still has to exist.
  • Response models with explicit fields. Serialize through a model per role that lists the fields to return, instead of returning the database entity.
  • Explicit binding on input. Accept only the fields a request is allowed to set; reject or ignore the rest.
  • Central authentication with strict token validation. Validate signature, issuer, audience and expiry on every request at a trusted layer.
  • Inventory as code. Generate the API description from the code or check it against the code in CI, so new routes cannot ship undocumented.

Who owns what

TaskYour teamA testing platform can help with
Decide who may access which objectYes, alwaysNo
Keep a current endpoint inventoryYesReading specs and collections, listing endpoints and hosts
Create test identities and dataYesSigning requests with the credentials you supply
Prove you may test a hostYesEnforcing verification and scope
Send consistent, non-destructive requestsSharedYes
Judge whether a 200 was correctYesOnly for checks with one right answer
Fix the codeYesLinking a runtime issue to its source path
Stop a regression from shippingSharedGating on findings in CI

How Safeguard does this

Everything in this section comes from Safeguard's documentation at docs.safeguard.sh, mainly the Application Security Testing page and the Integrations catalog, plus the description on the API Security card in the app's Integrations page. Where the docs do not show a screen or a command, this section describes the outcome instead. The commands below are as the docs show them; they were not run for this post.

1. Add the API Security integration

Safeguard API Security integration (GA) is added the same way as a repository or registry, from the Integrations page in the app (Settings, then Integrations). Its card describes it as "Authenticated API testing: BOLA/IDOR, auth & data exposure." That is the job this post is about: object level authorization, authentication and data exposure, tested with credentials, on an API you own.

The docs describe four ways to tell it what to test:

  • a live URL
  • an OpenAPI or Swagger file
  • a pasted curl command
  • a Postman collection

A Postman collection is the richest input because it already holds the hosts, paths, headers, bodies and auth for every request. The docs note that a collection needs no base URL: Safeguard reads the collection and tests the hosts its requests reach. That makes the collection your QA team already maintains a usable starting point for the inventory step above.

2. Upload the collection and its environment

The docs ask for the collection exported from Postman as Collection v2.1 (v2.0 also works), as a JSON file. If the collection's URLs use variables that are set in a Postman environment, export that environment too and upload it with the collection. Its values are merged into the collection and take priority over the collection's own values, the same way Postman applies an active environment.

How the requests are read, per the docs:

  • Variables come from the collection's Variables tab and the uploaded environment. Values that refer to other variables are followed, and Postman's built-in dynamic variables (such as the GUID and timestamp variables) are filled in.
  • Headers, request bodies (raw JSON, URL-encoded and text form fields, GraphQL) and auth are sent as the collection defines them.
  • Supported auth: bearer token, API key (in a header or the query string), basic auth, and an OAuth 2.0 access token already saved in the collection. Auth is inherited from folders and from the collection, as in Postman.
  • Scripts are not run. If a pre-request or test script sets a variable, usually a login request that stores a token, that value does not exist during the scan. The upload sheet warns you when this applies. The docs' advice is to put the value in the environment instead, ideally a token for a test account.
  • A request whose host comes from an undefined variable cannot be placed, so it is skipped and listed in the results. A path or query value nobody defined (an order ID variable, for example) is filled with a placeholder, and the request is still tested.

That last point matters for authorization testing. A placeholder identifier tests whether the endpoint responds safely to an unknown object; it does not test whether tenant B can read tenant A's real test object. For that, put real test object identifiers from your seeded data into the environment.

3. Verify that you own the target

Safeguard DAST (GA) will not run active checks against a target you have not verified. The docs list four ways to prove ownership:

MethodHow
DNS TXTAdd a provided TXT record to the target's domain
File uploadHost a provided token file at a well-known path
Meta tagAdd a provided meta tag to the site
Email domainVerify through an address on the target's domain

Until verification succeeds, the target stays unverified and the docs say only passive, non-intrusive checks, if any, are permitted. This is the platform version of step 2 in the plan above, and it is enforced in code rather than offered as a setting you can skip. The live post on DAST scope and verified targets goes deeper on this part.

4. Choose which hosts to test

Before the scan starts, the upload sheet lists every host the collection calls, and you choose which to test. Per the docs:

  • Your own hosts are ticked by default.
  • Well-known third-party services, such as payment, identity, email and messaging providers, are not ticked by default. Tick one only if you are authorized to test it.
  • Local and private addresses (localhost, private IP ranges, names ending in .local or .internal) cannot be reached from Safeguard's scanner and are not tested. Scan those with a runner inside your network.

The docs also describe how a scan shares its time across hosts: each scan has a cap on how many hosts it tests, it tests a small number at a time in order of how many requests each host has, and every host gets a fair share of the scan's time. Results for each host are kept even if another host is slow or fails.

5. Set scope, safety mode and limits

The docs list the DAST safety controls as enforced in code:

  • Strict scope. Every outbound request is checked against an allow-listed host and path scope. Out of scope requests are blocked and logged.
  • Rate limits and budgets. Conservative per-target limits on requests per second, requests per node and maximum duration are mandatory and configurable.
  • Non-destructive by default. Detection uses benign markers and bounded, time-based or out-of-band inference, never data-destroying or denial of service payloads.
  • Safety modes. passive, safe_active and authenticated_safe_active for normal use. A heavier lab_aggressive mode is off by default, never selected automatically, and needs elevated authorization plus a target flagged as owned and isolated.
  • Full audit trail. Every DAST request and finding change is recorded with actor, tenant and timestamp.

For API work with test account tokens, authenticated_safe_active is the mode that matches the plan above: requests carry the test identity's credential, and the checks stay non-destructive. The docs describe the runtime classes DAST tests for as missing security headers, injection classes and misconfigurations.

6. Run it from CI or a runner

The Safeguard CLI (GA) runs the same scans from a pipeline or a local machine. The docs show this command for dynamic analysis of a verified, in-scope target:

# Dynamic analysis of a verified, in-scope target
safeguard appsec dast \
  --target-id <target> \
  --base-url https://app.example.com \
  --scope-host app.example.com \
  --tenant-id <tenant>

The docs state that the DAST command refuses to run against an unverified or out-of-scope target, and that the safety kernel enforces this regardless of flags. For APIs that live on private addresses, the local runner (GA) built into the CLI executes the platform's scan jobs on your own machine, and the CLI docs say only results leave it. That is the route the docs point to for hosts Safeguard's scanner cannot reach.

7. Read the results

The project page shows a Hosts tested panel. For each host it says whether the host was tested in full, partly tested, did not answer, or was not tested and why, plus the requests that could not be sent. The docs make a point worth repeating in any report you send upward: a host that was not tested has no findings because it was not looked at, not because it is clean.

The same information appears as two informational findings: "Some hosts in the uploaded collection were not fully tested" and "Some requests in the uploaded collection were not tested". Treat both as inventory gaps to close, not as noise.

Findings appear in the app's AppSec views with severity, rule, CWE and location. The docs say there is no CLI command for listing them yet, so review them in the app or through Safeguard's other clients.

8. Handle credentials safely

Tokens, API keys and passwords in the collection or its environment are used to sign the scan's requests to the hosts you tick, and are stored with the uploaded file. The docs say they are removed from findings, the endpoint inventory and reports. Use a test account's credentials wherever you can, and rotate them on your normal schedule.

To update a collection, open the integration, choose Update and upload the new version of the collection and environment. The new file replaces the old one, and a scan starts when you save. Leave the upload empty to change only the name or the scan mode.

9. Link runtime findings to source code

Safeguard SAST (GA) analyzes source code without running it and traces untrusted input from a source, such as a request parameter, to a dangerous sink, such as a SQL query or a file path. Each SAST finding carries the dataflow trace, the CWE and OWASP mapping, severity and code location. The docs list JavaScript and TypeScript, Python and Java as the first languages.

SAST, DAST and SCA findings share one model with correlation keys. When a DAST-confirmed runtime issue maps to the SAST sink that produced it, the two are linked and prioritized together. The docs show the static command as:

# Static analysis of a source directory
safeguard appsec sast --dir ./src --tenant-id <tenant> --product-id <product>

For authorization work this pairing helps with the "fix at the source" step: a runtime finding on an endpoint is easier to route when it comes with the code path behind it. If you want the authenticated scan story told from the code side, see Safeguard DAST authenticated scans that start from the code.

10. Gate releases on what you find

Safeguard policies and gates (GA) evaluate findings in CI and act on them with one of three actions. Per the Policies and Gates docs: Block means the gate fails, Warn means the gate passes with a warning naming the policy, and Notify means the gate passes and a notification is sent. When a finding is understood and accepted for a limited time, approval runs through a policy exception rather than by turning the gate off. In practice, teams start a new API's gate on Warn while the matrix fills in, then move the categories they trust to Block.

How the OWASP entries map

OWASP API 2023 entryWhat Safeguard's docs describeWhat you still own
API1 BOLAAuthenticated BOLA and IDOR testing on verified targets, with in-scope, non-destructive requests signed with the test credential you supplyTest identities and seeded test objects in the environment; deciding the fix
API2 Broken AuthenticationAuthenticated testing of auth, using the auth your collection defines (bearer, API key, basic, saved OAuth 2.0 token); findings in AppSec viewsToken lifetime, revocation and login flow design
API3 Property level authorizationData exposure testing, endpoint inventory, and findings with severity, rule and CWEField allow-lists per role, so a finding can be checked against intent
API5 Function level authorizationHosts and requests listed per scan; gates on findingsThe role axis of the access matrix
API9 InventoryHosts tested panel, skipped requests listed, informational findings for gapsRetiring old versions and documenting every route

What Safeguard does not do

  • It does not write your access rules or test identities for you. Safeguard's authenticated BOLA and IDOR, auth and data exposure testing works with the credentials and values you put in the collection and its environment. Undefined path or query values are filled with placeholders, so supply real test object identifiers and test account tokens if you want the testing to reach real test data. The access policy itself, and any fix to it, remain decisions for your team.
  • It does not run Postman scripts. Pre-request and test scripts are skipped, so tokens a login script would set are missing unless you put them in the environment. Chained flows that depend on scripts need a different approach.
  • It does not test hosts you have not verified or did not tick. That is by design. Third-party services in your collection stay unticked unless you are authorized, and unverified targets get passive checks at most.
  • It does not reach private addresses from its own scanner. Localhost, private IP ranges and .local or .internal names need a runner inside your network.
  • It does not run destructive or denial of service tests in normal modes. The heavier lab mode is off by default and needs elevated authorization and an owned, isolated target. If you need load or abuse testing, plan it separately.
  • It does not fix the authorization logic for you. Remediation for access control flaws is a code and design change your engineers make and review.
  • It does not turn "not tested" into "clean". Hosts and requests that were skipped are reported as not tested. Your report should say so too.

Common mistakes

  • Testing with one identity. A single test account can only prove that the API works for its owner. BOLA needs at least two tenants.
  • Leaving tokens in login scripts. If the token only exists because a script ran, an automated scan will run unauthenticated. Put a test account token in the environment.
  • Trusting UUIDs. Unpredictable identifiers slow enumeration; they do not replace a check.
  • Checking status codes only. A 200 with three extra fields is an API3 finding. Compare bodies with field allow-lists.
  • Ticking third-party hosts "to be thorough". Only test what you own or have written permission to test.
  • Reading an empty findings list as a pass. Check the Hosts tested panel and the skipped requests first.
  • Using production customer data. Seed test tenants. If you must test in production, use test tenants that hold no real data and agree the window.
  • Fixing the endpoint, not the pattern. If one endpoint missed an ownership check, its siblings probably did too. Search the code for the same query pattern and add matrix rows for them.

FAQ

What is the difference between BOLA and IDOR?

They describe the same flaw from two traditions. IDOR is the web testing term in the OWASP Web Security Testing Guide; BOLA is the API Security Top 10 name, API1:2023. Both mean the server uses an object reference from the client without checking the caller may access that object.

Can an automated scanner find BOLA on its own?

A scanner needs inputs to do it well: authenticated identities and real test objects to request. Safeguard's API Security integration runs authenticated API testing for BOLA and IDOR on verified targets using the credentials and values in your collection and environment. Keep your own access matrix too, so you can check findings against what each role is meant to reach.

Which OWASP API Top 10 entry covers excessive data exposure now?

API3:2023, Broken Object Property Level Authorization. The 2023 edition merged the 2019 entries for excessive data exposure and mass assignment into it.

How do I scan an API with Safeguard if my collection uses a login script?

Scripts are not run during a scan, so the token the script would set does not exist. Export a Postman environment with a token for a test account and upload it with the collection. The upload sheet warns you when a script sets a variable.

Does Safeguard test third-party APIs that my collection calls?

Not by default. Well-known third-party services such as payment, identity, email and messaging providers are unticked on the upload sheet. Tick one only if you are authorized to test it.

Can Safeguard scan an internal API on a private network?

Safeguard's scanner cannot reach localhost, private IP ranges or .local and .internal names. Run the scan with a runner inside your network instead.

How does Safeguard prove I am allowed to test a target?

You verify ownership with a DNS TXT record, a hosted token file, a meta tag or an email address on the target's domain. Active checks cannot run until verification succeeds.

Are my API tokens exposed in Safeguard reports?

Per the docs, credentials in the collection or environment sign the scan's requests and are stored with the uploaded file, and they are removed from findings, the endpoint inventory and reports. Use test account credentials.

What does "partly tested" mean in the Hosts tested panel?

Some of that host's requests were sent and some were not. The panel lists the requests that could not be sent and why. Treat the untested ones as unknown, not safe.

Can I block a release on API security findings?

Yes. Safeguard policies and gates act on findings with Block, Warn or Notify, and accepted risks go through exceptions with approval.

Closing the loop on the fix

Authorization flaws are fixed in your own code, but the same release often carries a vulnerable dependency that the API's owners cannot wait on. The block below describes how Safeguard handles that side of the fix when the upstream maintainer has not shipped one yet.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.

3. Gold Registry: start from components that are already fixed

Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingSafeguard policies and gates in CI
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

The first demo is a real Safeguard CLI session: it installs the CLI, opens the interactive terminal and asks it to fix a lodash CVE in a repository. The CLI reads the finding and advisory, asks before any command that changes something, edits the dependency, runs the install and tests with approval, prints a summary and pushes nothing. It is not an API Security scan, but it is the same CLI that runs the documented appsec commands, and the same approval habit applies when you fix an authorization finding.

Click through it at your own pace, or open it full screen.

The second demo sets up the local runner on your own machine, approves it with its device code, then scans from the terminal. For APIs on localhost or private addresses that Safeguard's scanner cannot reach, a runner inside your network is the documented route.

Click through it at your own pace, or open it full screen.

The third demo connects Claude to the Safeguard MCP server with OAuth and chooses which tools Claude can use. Once connected, you can ask about findings in plain language; the API tests themselves still run through the integration, the CLI or a runner, against verified targets only.

Click through it at your own pace, or open it full screen.

Quick check

Why can a scanner not confirm a BOLA finding on its own?

Because a 200 response is only wrong if the caller should not have access to that object. Ownership and access rules are business facts the scanner has to be given, through test identities, seeded objects and an access matrix.

Your Postman collection gets its token from a login script. What do you do before scanning it with Safeguard?

Scripts are not run during a scan, so put a test account token in a Postman environment, export it and upload it with the collection.

Sources

Download Safeguard at https://safeguard.sh/download and read the docs at https://docs.safeguard.sh/docs .

Last reviewed: 25 October 2026. Product capabilities change; check docs.safeguard.sh for the current state.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.