Neutron, our AI engine, scored 97.1% on UC Berkeley's CyberGym benchmark. Learn more

Security

Security

Why API Security Testing Misses Cross-Asset Attack Chains

API-only scanners miss attack chains that start with secrets or routes in mobile apps, web bundles, or code. Two real chains and an 8-step test checklist.

Your API scanner can hand back a clean report while an attacker walks right in. Their request is valid and carries a real token, and the server responds to it correctly. The problem is where the token came from. It was somewhere your scanner never checked: a string compiled into your mobile app, a route left behind in a JavaScript bundle, or a secret still sitting in Git history.

API security testing alone fails because many high-impact API breaches don't start at the API. They start with a credential, route, or request format pulled from a mobile app, a JavaScript bundle, or source code, and then replayed as a valid request. A scanner that tests only the API never sees where the chain begins.

In one iOS app we assessed, a hardcoded Auth0 secret led to a 1,000-record user directory, even though the first finding on that credential had already been marked Fixed & Verified. That story is below. This guide is for AppSec leads and DevSecOps engineers whose APIs serve mobile or web clients.

Executive Summary (TL;DR)

  • In our assessments, many of the most severe API findings didn't start at the API. They started with a credential or a route pulled from a client app or from code, which then got replayed as a valid request.
  • Scanners that test one asset at a time each see half of that chain. Collecting their reports in one dashboard afterwards doesn't connect the halves.
  • To catch these chains, test the client apps, the code, and the live API in the same assessment, and make the fixes on the server side.

What is a cross-asset attack chain? A cross-asset attack chain is a series of weaknesses spread across more than one asset, such as a mobile app, a web frontend, a source repository, and a backend API. Each weakness looks minor on its own. Together they give an attacker access to data or functions they should never reach.

The typical chain has three moves:

  1. Extract something from a client or from code: a token, a signing key, an undocumented route, or a request format.
  2. Replay it against a backend API as a valid request.
  3. Escalate through an authorization gap on the server: another user's object (BOLA), a privileged function (BFLA), or a broader token scope.

No single step here looks like an attack. The first is a static string, the second is an authenticated request, and the third is an ordinary API response. The breach only shows up when you read them in order.

What do cross-asset attack chains look like in practice?

The two chains below come from real Ostorlab assessments, each published in more detail on this blog. Both involved Ostorlab Agentic Deep Scan, which runs autonomous testing agents against an asset: a mobile binary in the first case and source code in the second. Each became a confirmed breach only when the extracted credential or route was replayed against the live backend.

1. From a hardcoded Auth0 client secret in an iOS app to tenant-wide admin scopes

In an assessment covered in How AI Catches Complex Vulnerabilities, an iOS app shipped with an Auth0 machine-to-machine (M2M) client_id and client_secret. Both were embedded at build time through Flutter's DART_DEFINES. The app used them to call one internal service.

The first finding on this credential, scoped to the one audience the app calls, had been rated High and was already marked Fixed & Verified. The fix closed the path the app used, not everything the credential could reach.

A static scanner would report the string. Given the audience the app legitimately requests, an API scanner would see a correctly scoped token. But the agent asked a different question. An M2M client can be granted access to more than one API, so what else was this client authorized to call?

It tried 38 candidate audiences against the tenant's /oauth/token endpoint. The Auth0 Management API (https://<tenant>.auth0.com/api/v2/) came back with HTTP 200 and a token holding eight administrative scopes, among them update:users, delete:users, and create:client_credentials. A single read-only GET then exposed the tenant's entire 1,000-record user directory, PII included. No write was performed, but the token could have created, updated, and deleted users. That second finding was rated Critical and was still Open.

Five-step attack chain: a hardcoded Auth0 credential found in an iOS app, confirmed active, its production JWT analyzed, Auth0 Management API access validated, and tenant-wide impact demonstrated with a non-destructive request
Auth0 M2M Credential to Management API Attack Chain
Figure 1: An M2M credential extracted from an iOS binary escalates into administrative scopes on the Auth0 Management API.

Why a single-layer test misses it: the credential lives in the binary, and the over-scoped grant lives in the identity provider's configuration. Neither shows up in the API spec.

2. The create endpoint that transferred ownership (BOLA)

In the GoPhish source-code assessment, where a manual review was paired with Ostorlab Agentic Deep Scan, the group creation endpoint (POST /api/groups/) performed a silent upsert. A valid JSON body carrying the id of another user's group overwrote that group's recipient data and transferred ownership to the attacker.

Agentic Deep Scan surfaced the pattern in the code, where create handlers accepted an id. The assessment then confirmed it by replaying the request as a second user against an isolated local GoPhish instance with synthetic accounts. That replay overwrites data, so it belongs in a lab, not in production.

Sanitized API evidence: an admin creates group 106, a second user sends a create request carrying id 106, and the admin then gets 404 while the second user gets 200
Cross-user group takeover through a create request
Figure 2: Sanitized evidence from the GoPhish assessment. A second user takes over an existing group through a create request carrying its ID. Account names, API keys, and endpoints are synthetic.

Why a single-layer test can miss it: the request was well-formed and authenticated, and the flaw is in ownership logic, not input validation, so contract checks and schema-based fuzzing have nothing to flag. A multi-user test only catches it if it sends another user's ID in a create request. Reading the handler shows exactly where to try that.

Why do single-layer API scanners miss these chains?

Single-layer scanners miss these chains because each one sees only its own asset, so none of them connects a secret found in a client to the API that secret unlocks. Most security tools cover one corner of the stack: source code, gateway or WAF traffic, or test requests against a staging server. None of them is broken; each tests its own asset in isolation.

But backend APIs are called by mobile binaries (iOS .ipa, Android .apk), single-page web apps, partner integrations, and internal services, and all of them ship configuration, and often secrets, to places an attacker can read. Tested one at a time, each asset can pass while the chain between them goes unnoticed. Some platforms now combine code, runtime, and API testing, which is what these chains need.

Where do API credentials and routes leak from?

API credentials and routes usually leak from five sources an attacker can pull from: mobile binaries, web bundles, source repositories and CI, API documentation, and secondary channels such as WebSockets. These are the ones we run into most often in assessments:

Source What an attacker extracts Typical API impact
Mobile binaries (APK / IPA / AAB) Confidential credentials that should never ship in an app, such as M2M client secrets and shared client_secret values (a native app's public client_id is expected to be visible), privileged API keys injected at build time (for example, Flutter DART_DEFINES or Android BuildConfig), encryption keys and request-signing logic, hidden or debug endpoints Token minting, bypassed request signing, calls to internal or staging APIs
Web bundles (SPA JavaScript, source maps) Admin and internal routes the UI never shows, feature-flagged endpoints, third-party API keys, GraphQL operation names Undocumented endpoints (shadow APIs), privileged functions reachable without UI checks (BFLA)
Source repositories and CI Secrets in commit history, deploy tokens, route definitions, handlers missing authorization middleware Direct authenticated access, and a precise list of routes without ownership checks
API documentation and collections (OpenAPI, Postman, GraphQL introspection) Full request shapes, deprecated versions that are still live, object identifier formats Mass enumeration and access through old API versions (improper inventory management)
Secondary channels (WebSockets, gRPC-web) Endpoint paths and operation names exposed by the channel, and handshakes that skip the HTTP authentication middleware Unauthenticated data streams or subscriptions (broken authentication, BFLA)

A scanner working only from an OpenAPI file and a test account starts without any of these artifacts. So it tests the API that a well-behaved client uses. It doesn't test the one an attacker will use.

Which OWASP API Top 10 risks are easier to find with context from outside the API?

The risks in the OWASP API Security Top 10 (2023) are server-side flaws: BOLA and BFLA are always fixed in the API. But several of them are easier to discover or validate with context from outside the API, such as a client app or the source code:

OWASP API risk External context that helps find or validate it What an API-only scan sees
API1: Broken Object Level Authorization (BOLA) Object identifier formats and request encryption learned from the client app Requests for its own test objects, which succeed as expected
API2: Broken Authentication Client credentials or long-lived tokens extracted from a binary or repository Nothing, unless someone hands it the leaked credential
API3: Broken Object Property Level Authorization Hidden fields found in client models or GraphQL types Only the fields documented in the spec
API5: Broken Function Level Authorization (BFLA) Admin routes in web bundles, and secondary channels such as WebSockets The HTTP routes listed in the spec, and only the roles its test account was granted
API8: Security Misconfiguration Over-scoped OAuth clients, audiences, or cloud roles tied to a shipped credential Transport and header issues on the endpoints it knows
API9: Improper Inventory Management Staging hosts, old versions, and debug endpoints referenced in clients and code Only the inventory it was given

The other four (API4 Unrestricted Resource Consumption, API6 Unrestricted Access to Sensitive Business Flows, API7 SSRF, and API10 Unsafe Consumption of APIs) are usually tested from the API side.

Why don't API gateways, ASPM platforms, or scanner pipelines catch these chains?

Most teams already have an API gateway, an ASPM platform, or a CI pipeline that runs several scanners. Each helps, but on its own none of them tests a leaked credential against the API. Take a common chain: a mobile app ships a hardcoded API token, an attacker calls the backend with it, and a misconfiguration gives that token administrative rights.

The API gateway lets the request through

A gateway checks that requests are well-formed, applies rate limits, and verifies that tokens are genuine and correctly signed. In this attack the request is valid and the token is real. The gateway has no way to know that a token shipped inside a public app should never carry administrative rights.

ASPM aggregation doesn't connect the dots

Application Security Posture Management (ASPM) platforms collect findings from mobile, code, and API scanners into one view. That helps with triage and ownership. But when the correlation happens after the scans finish, nothing gets tested across assets. Some platforms bundle their own scanners, so the distinction that matters is when correlation happens, not the product category:

Dimension ASPM aggregation In-scan correlation
When correlation happens After each scanner has finished During the scan, while tests are still running
What gets correlated Findings that already exist Raw discoveries: tokens, routes, request formats
Can it test a leaked token against the API? Not through aggregation alone; it links two findings Yes, the token becomes input for the next live test
Output Two related findings, often with different severities One validated chain with request and response evidence
Severity Inherited from each scanner Based on the demonstrated impact of the chain

A scanner pipeline runs tools in sequence, not together

Chaining scanners in CI runs them one after another, but none sees what the others found. The mobile scanner finds a client secret in the APK or IPA, can't tell where it works, and files a low-severity static finding. The API scanner tests the backend from the public schema and never learns about the secret.

How does a multi-asset scan test the whole chain?

In-scan correlation means a discovery in one asset, such as a route in source code or a token in a client binary, immediately becomes input for tests against the live backend. Ostorlab's Multi-Asset Deep Agentic Scan is built on this idea. Where Agentic Deep Scan investigates one asset at a time, Multi-Asset Deep Agentic Scan runs one agentic investigation across related assets, including the mobile app, backend APIs, web frontends, and source code, in a single scan.

Adding assets to an Ostorlab Multi-Asset Deep Agentic Scan: app store and uploaded mobile apps, web apps, networks, code repositories, and files
Adding assets to a Multi-Asset Deep Agentic Scan
Figure 3: Adding assets to a Multi-Asset Deep Agentic Scan: mobile apps from a store or as a file, web apps, networks, code repositories, and supporting files such as API schemas.

Inside the scan, mobile binaries, web frontends, backend APIs, and source code all feed one live validation step, where a leaked token or route is tested against the backend. The scan works in three stages:

  1. Discovery. The agent decompiles mobile binaries (APK, AAB, and IPA), reads web JavaScript bundles, source maps, repositories, and documentation, and runs the apps on instrumented Android and iOS devices while capturing their traffic. It also probes well-known OpenAPI and Swagger locations and runs GraphQL introspection. An OpenAPI (Swagger 2.0 or OpenAPI 3.x) or GraphQL schema improves coverage from the start, but it isn't required.
  2. Correlation. Client-side artifacts such as endpoints, base URLs, OAuth audiences, request parameters, and embedded tokens are matched against the backend's routes and services. A secret found in code or bytecode is treated as a lead to investigate, not as a confirmed vulnerability.
  3. Validation. Each plausible attack path goes to an exploitation agent, which tests it against the live backend, for example by checking whether a token authenticates or whether an endpoint returns data it shouldn't. Validated findings include the exact requests and responses, so your team can reproduce them.

Many secret scanners report credential-shaped strings, and even those that check whether a key is live don't test what it can reach through your API. Here a chain, and the higher severity that comes with it, is only reported once it's reproduced. Standalone findings are still reported on their own merits: a leaked credential that doesn't work today is still worth fixing.

Protocol coverage today:

  • GraphQL: mapped through introspection over HTTP or an uploaded schema, then tested with generated queries and mutations.
  • SOAP: tested live.
  • gRPC: analyzed from .proto definitions for authorization and data-exposure risks. Live gRPC calls and server reflection aren't supported yet.
  • WebSocket and GraphQL subscriptions: Multi-Asset Deep Agentic Scan doesn't yet run live tests over WebSocket transports.

The WebSocket authorization flaw cited in step 6 of the checklist below was found in a separate, targeted assessment by Ostorlab's AI Pentest Engine; in a multi-asset scan, WebSocket authorization remains a manual check.

Is autonomous API testing safe to run against your backend?

Yes, with guardrails and a staging target. An agent that tests live APIs has to prove impact without causing damage, so Ostorlab layers its controls:

  • Agent instructions. Agents demonstrate impact with the smallest safe action: a BOLA or BFLA flaw is shown by an unauthorized read, not by changing records, and tokens are checked with read-only requests. Agents don't run destructive commands, open reverse shells, establish persistence, modify data, or revoke credentials.
  • A supervisor outside the AI model. A separate supervisory program checks every tool call and destination against the scan's scope before it runs, blocks out-of-scope requests, and shuts the scan down if an agent keeps trying to leave scope. Our post-mortem on AI agent scope drift explains why this layer matters.
  • Controls outside the agents. Firewall rules limit what scanning agents can reach, and request volume is capped at the scanner host.

We still recommend running multi-asset scans against a staging or pre-production environment, with dedicated test accounts. For internal APIs, an on-premises scanner runs as a container inside your infrastructure and only opens an outbound connection to receive jobs and return findings. For staging APIs behind a WAF or IP allowlist, allowlist the scanner IP addresses published in the Ostorlab documentation. Client certificates aren't a scan setting yet, so for APIs behind mutual TLS, run the on-premises scanner behind the point where mTLS is terminated, so the scanner never needs a client certificate.

How can you test your own stack for cross-asset chains?

You can start with open-source tools and a few hours of focused work. Work through these eight steps to find mobile-to-API, code-to-API, and cross-transport chains:

  1. List every client of the API. Include each mobile app, web frontend, partner integration, and internal service that calls it, and the credentials each one holds.
  2. Extract what the clients ship. Decompile the latest Android builds (jadx -d out app.apk or apktool d app.apk). For iOS, run unzip app.ipa -d out on a decrypted IPA; App Store builds are FairPlay-encrypted, so strings in the binary aren't searchable until it's decrypted. Download the production JavaScript bundles and any source maps into the same folder. Then search for keys and tokens (grep -rEai "api[_-]?key|secret|token|bearer" out/, where -a makes grep print matches inside compiled binaries) and for hostnames (grep -rEaoh "https?://[a-zA-Z0-9./_-]+" out/ | sort -u). For a single binary, strings -a <binary> | grep -Ei "secret|token" works too.
  3. Test every credential you find, within scope. For each OAuth client, request tokens for the other resource servers and scopes you're authorized to test (Auth0 calls this parameter audience; RFC 8707 calls it resource). Don't enumerate blindly beyond what the engagement allows. For each API key, check which in-scope hosts and environments accept it. Our guide on finding and validating hardcoded secrets shows how to check what a leaked key can do.
  4. Compare discovered routes with the spec. A route that appears in a client or in code but not in the OpenAPI or GraphQL schema is a candidate shadow API. It may be intentionally undocumented, dynamic, or out of scope, so confirm it's live, API-facing, unmanaged, and authorized for testing before treating it as one.
  5. Test authorization with a role-by-tenant account matrix. Two generic users aren't enough. For every operation, test same-role access across tenants and cross-role access within a tenant, including create endpoints that accept an id.
  6. Test every transport, not just HTTP. Each one needs its own checks. For WebSockets, test authorization at connection time and on every operation. For gRPC, test method-level authorization and metadata handling. For webhooks, verify signatures, timestamps, replay protection, and tenant routing. In one GraphQL assessment by Ostorlab's AI Pentest Engine, the API enforced roles over HTTP but accepted unauthenticated WebSocket subscriptions.
  7. Check old versions and hosts. Call /v1/ where /v2/ is current, and try staging hosts referenced in the clients. Here's how an API version mismatch led to account takeover.
  8. Repeat on every release. A new mobile build can ship a secret the last assessment never saw.

Want to automate this checklist? Multi-Asset Deep Agentic Scan automates the extraction, credential, route, and authorization steps in one scan: it pulls what your mobile app ships, tests credentials and routes against the live API, and reports the chains it reproduces. WebSocket checks from step 6 stay manual for now.

How do you prevent cross-asset attack chains?

These fixes are architectural. They live on the server side or in how clients are built:

  • Keep privileged secrets out of clients. Treat anything shipped in a mobile app or web bundle as public. Native apps should sign users in with the Authorization Code flow with PKCE, so they only hold short-lived, per-user tokens. Browser apps can use a backend-for-frontend (BFF) to keep tokens off the client. Our guide on hardcoded secrets covers the common patterns.
  • Scope machine credentials tightly. Grant each M2M client access to one API with the smallest set of scopes it needs, and alert on token requests for other audiences.
  • Retest the credential, not just the path. When you fix a leaked credential, check every audience and scope it can still reach, not only the one the app uses.
  • Enforce ownership on the server for every operation. Resolve the object from the authenticated user, never from an id in the request body alone. On create, reject identifiers of existing server-owned objects (or enforce insert-only semantics) and check ownership. Client-generated UUIDs for new objects can be fine.
  • Use one authorization policy across transports. WebSockets and gRPC can't always reuse HTTP middleware, so define the policy centrally and enforce it at each boundary: the connection, each operation or resolver, each message or event, and gRPC interceptors.
  • Treat inventory as a security control. Retire old versions and staging hosts, and keep the spec in sync with what clients actually call.

Frequently Asked Questions (FAQ)

What is a cross-asset attack chain in API security?

A cross-asset attack chain combines weaknesses in more than one asset, such as a mobile app, a web frontend, source code, and a backend API. A typical chain extracts a credential or route from a client, replays it as a valid API request, and escalates through an authorization gap such as BOLA or BFLA.

Why can't API scanners detect secrets hardcoded in mobile apps?

API scanners test the running backend with the credentials and specification they are given. They don't decompile mobile binaries, so they never see secrets compiled into the app, and they have no reason to test those secrets against the API.

What is the difference between ASPM and multi-asset scanning?

ASPM platforms aggregate findings from separate scanners into one dashboard after each scan has finished. Multi-asset scanning performs in-scan correlation: a discovery in one asset, such as a token in a mobile binary, is used during the same scan to run live tests against the backend API, and only reproduced chains are reported.

Which OWASP API Top 10 risks are easier to find with client or code context?

All OWASP API Top 10 risks are fixed on the server, but Broken Object Level Authorization (API1), Broken Authentication (API2), Broken Object Property Level Authorization (API3), Broken Function Level Authorization (API5), Security Misconfiguration (API8), and Improper Inventory Management (API9) are often easier to discover or validate with credentials, routes, or request formats taken from mobile apps, web bundles, or source code.

How do you test a mobile app's backend API for BOLA?

Decompile the app to learn its endpoints, identifier formats, and any request signing or encryption. Then create objects with one account and read, modify, and delete them with a second account, replaying the app's exact request format. Repeat for create endpoints that accept an object ID.

Is it enough to rotate a leaked mobile API key?

It depends on the key. Some mobile API keys are designed to be public and are restricted by app, platform, or quota, so exposure alone isn't a breach. For a leaked privileged secret, rotation alone isn't enough, because the next build will ship the new secret the same way. Revoke and rotate it, then remove it from the client and issue short-lived, per-user tokens from a backend service.

Why did we build multi-asset testing?

We kept seeing teams run separate scanners for code, mobile apps, and APIs and reconcile the results by hand, while the chains that mattered ran through credentials pulled from client binaries.

That's why we built Multi-Asset Deep Agentic Scan: one loop that turns a token found in a client binary into a live test against the backend, and reports only the chains it reproduces.

If you're comparing API testing tools more broadly, see our comparison of API security testing tools in 2026. To see what a multi-asset scan finds on your own mobile apps and APIs, book a demo with our security engineering team.