Skip to main content
Engagement composite · Banking

The package told us what to send. The API accepted it

A signed release build, taken as published, with obfuscation and certificate pinning intact. What came out of it was not access — it was knowledge of the interface behind it: the routes the client was built against, the header set the server expects, and the shape of the identifier it sends. Every step after that ran against the server, and each one used something the previous step handed it.

Sector
Banking
Coverage class
Mobile apps

The chain, step by step

5 steps, and what each one handed to the next

Each row names the technique, the weakness it maps to and what the step yielded. A finding that hands nothing to the next step is a finding, and belongs in the report rather than here.

StepWhat it yieldedSeverity
01 · Constants recovered from the decompiled build A service credential, and the route table the client was built against — including routes the shipped interface never calls. High
The signed store build is decompiled as published and the static pass reads what the client carries: string constants, resource files, build-time configuration and the call definitions compiled into it — CWE-798, Use of hard-coded credentials.
02 · A cryptographic key held in the client The ability to construct a request body the server treats as client-issued, rather than only to replay one that had been observed. High
The same pass recovers the symmetric key the client applies to an outbound payload field, held in the binary rather than derived per session or per installation — CWE-321, Use of hard-coded cryptographic key.
03 · A call path that left the device in the clear The live header set and the account-identifier format, read off the wire rather than inferred from the decompiled code. Medium
Dynamic analysis runs with certificate pinning and the runtime protections around it handled inside the run, and one call path is observed leaving the device without transport encryption — CWE-319, Cleartext transmission of sensitive information.
04 · An identifier the caller chooses Confirmation that the identifier alone authorises the read, and a working request template that could be pointed at every route in the table from step one. Critical
A request built to that shape — the header set from the observed call path, the payload field produced with the recovered key — is sent against api.mobile-banking.example with a valid session for an authorised test account, altering only the account identifier, and the server returns the record belonging to the altered value — CWE-639, Authorisation bypass through user-controlled key.
05 · A route that asks the caller for nothing The chain closed in a single artefact: a constant inside a published package, through to a server function that authenticates nobody. Critical
One route from that table, never reachable through the shipped interface, performs a state-changing operation and accepts the request with the session header removed entirely — CWE-306, Missing authentication for critical function.

01 · Constants recovered from the decompiled build

What it yielded
A service credential, and the route table the client was built against — including routes the shipped interface never calls.
Severity
High

The signed store build is decompiled as published and the static pass reads what the client carries: string constants, resource files, build-time configuration and the call definitions compiled into it — CWE-798, Use of hard-coded credentials.

02 · A cryptographic key held in the client

What it yielded
The ability to construct a request body the server treats as client-issued, rather than only to replay one that had been observed.
Severity
High

The same pass recovers the symmetric key the client applies to an outbound payload field, held in the binary rather than derived per session or per installation — CWE-321, Use of hard-coded cryptographic key.

03 · A call path that left the device in the clear

What it yielded
The live header set and the account-identifier format, read off the wire rather than inferred from the decompiled code.
Severity
Medium

Dynamic analysis runs with certificate pinning and the runtime protections around it handled inside the run, and one call path is observed leaving the device without transport encryption — CWE-319, Cleartext transmission of sensitive information.

04 · An identifier the caller chooses

What it yielded
Confirmation that the identifier alone authorises the read, and a working request template that could be pointed at every route in the table from step one.
Severity
Critical

A request built to that shape — the header set from the observed call path, the payload field produced with the recovered key — is sent against api.mobile-banking.example with a valid session for an authorised test account, altering only the account identifier, and the server returns the record belonging to the altered value — CWE-639, Authorisation bypass through user-controlled key.

05 · A route that asks the caller for nothing

What it yielded
The chain closed in a single artefact: a constant inside a published package, through to a server function that authenticates nobody.
Severity
Critical

One route from that table, never reachable through the shipped interface, performs a state-changing operation and accepts the request with the session header removed entirely — CWE-306, Missing authentication for critical function.

What the report carried

One report, and what sat behind each half of it

Findings in a client binary and findings on a server interface arrive differently, and both arrive with the same five things. This is what each looked like, and why they were not filed as two pieces of work.

What arrives with a findingOn the package halfOn the interface half
The request and the response A static finding has no request on the wire, so the artefact is the call site: where the constant sits in the decompiled build, what the client does with it, and the outbound call it is used to assemble. The request as sent and the response as returned, header for header, against api.mobile-banking.example.
Steps to reproduce The build taken, the step that decompiles it and the location inside it, so an engineer recovers the same constant from the same artefact without being told where to look. The ordered calls: obtain a session for an account you control, take the identifier format from the package, alter it, send it, read what comes back.
A CVSS v4.0 vector Scored on the weakness in the client as shipped. Scored on what the server did with the request, which is where both Critical ratings in this chain sit.
The weakness mapping CWE-798 for the credential, CWE-321 for the key. CWE-319 on the clear call path, CWE-639 on the identifier, CWE-306 on the route that authenticates nobody.
Whose signature it went out under A senior Security Brigade auditor verified it before the report was issued. The same auditor, in the same verification pass. One report, one signature, both halves.
The delivery model is autonomous expert verified. Security Brigade has been CERT-In empanelled since 2008.

The request and the response

On the package half
A static finding has no request on the wire, so the artefact is the call site: where the constant sits in the decompiled build, what the client does with it, and the outbound call it is used to assemble.
On the interface half
The request as sent and the response as returned, header for header, against api.mobile-banking.example.

Steps to reproduce

On the package half
The build taken, the step that decompiles it and the location inside it, so an engineer recovers the same constant from the same artefact without being told where to look.
On the interface half
The ordered calls: obtain a session for an account you control, take the identifier format from the package, alter it, send it, read what comes back.

A CVSS v4.0 vector

On the package half
Scored on the weakness in the client as shipped.
On the interface half
Scored on what the server did with the request, which is where both Critical ratings in this chain sit.

The weakness mapping

On the package half
CWE-798 for the credential, CWE-321 for the key.
On the interface half
CWE-319 on the clear call path, CWE-639 on the identifier, CWE-306 on the route that authenticates nobody.

Whose signature it went out under

On the package half
A senior Security Brigade auditor verified it before the report was issued.
On the interface half
The same auditor, in the same verification pass. One report, one signature, both halves.

The delivery model is autonomous expert verified. Security Brigade has been CERT-In empanelled since 2008.

Why it is one report

A mobile assessment that stops at the package is half an answer

Read on its own, the first half of this engagement is a report about a client binary: secrets that should not be in a shipped artefact, and a call path that should have been encrypted. Every one of those findings is true, and a team could act on all of them without the server changing at all — which is exactly the problem, because the finding that mattered lives in the server. The package was not the vulnerability. The package was the specification: it told us which routes existed, what the server expected in each header, and how an account identifier was formed. An interface assessment scoped on its own starts by working that out, and works it out from the outside. Here it was read out of the artefact the customer publishes to an app store. That is why the two halves were authorised, run, verified and reported together rather than sequenced as two engagements with two scopes and two reports.

Three ways to scope it

What each scoping decision can reach, and where it stops

The same environment, viewed from the three ways a buyer normally divides it up. Two of the three are perfectly good assessments that could not have produced this chain.

01 Mobile only

The package on its own

What it reaches
Everything the client holds and everything it does on the device: the constants, the key, the storage, the transport, the runtime behaviour once the protections are handled.
Where it stops
At the edge of the device. It can report that a credential is in the build; whether the server still honours it is a question outside the scope, and the report says so.
02 API only

The interface on its own

What it reaches
Every authorisation decision the server makes on the routes it was given, worked role by role with a credential for each.
Where it stops
At the routes it was given. A route the shipped interface never calls does not appear in traffic, so it has to come from documentation that may not describe it, or from the artefact the client is built into.
03 This engagement

Both, under one authorisation

What it reaches
The same two sets of findings, plus the joins between them — which is the part neither scope produces on its own.
Why it goes further
Each step in the chain consumed something the step before it produced. Split the scope and the producing step and the consuming step land in different reports, owned by different teams.

The joins

What each step actually handed the next one

The table above lists the steps. This is about the gaps between them, which is where a chain is either real or merely asserted.

None of the material recovered from the package granted access to anything. What it removed was guesswork. The route table meant the server’s surface did not have to be inferred from the traffic the client happens to generate, so a route the interface never calls was in scope from the first step rather than being found by accident. The key meant a request body could be constructed rather than replayed, which is the difference between repeating one observed transaction and shaping an arbitrary one. The clear call path supplied the header set and the identifier format, so the request sent at step four was well formed on the first attempt and the server’s response was a decision about authorisation rather than a rejection of a malformed call. Then the authorisation bypass produced the thing the last step needed, which was not data but a verified request template — proof that a request in this shape was accepted, which is what made it worth sending the same shape at a route nobody had ever called from a phone.

Counterfactual

What each half would have concluded on its own

Both of the scopes below produce true findings and a defensible report. Neither produces the last two steps.

What each half would have concluded on its own
StateWhat it meansWhat follows
Package only Secrets recovered from a shipped artefact, and a call path without transport encryption. Remediation reads: rotate, move the secrets server-side, encrypt everything. Correct advice, and the server keeps honouring the identifier.
Interface only The routes supplied by the customer are worked role by role, and the authorisation decisions on them are tested properly. A route the client never calls is only in scope if somebody remembered it.
Both, in one authorisation Terminal The static half feeds the dynamic half inside a single scope, so what the client was built to send is checked against what the server is willing to accept. The chain reconstructed end to end, in one artefact, under one signature.
Key
  • True findings, with the other half of the chain outside the scope
  • Both halves inside one authorisation
  • TerminalNo state follows this one

What changed

The changes made, and what confirmed each one

Most of them are server-side. That is the part a mobile-only report cannot ask for, because nothing done inside the client would have made the last two steps safe.

The changeWhereWhat confirmed it
Rotate the credential, then stop shipping it Server, then build Rotation confirmed against the server first, because a credential removed from the next build is still live until it is revoked. The new build was then decompiled again and the retest looked for the constant itself rather than for its effect.
Move the key off the client Server The payload field is produced where the key can be held. Confirmed by constructing the same request from the recovered key and having it refused.
Transport encryption on every call path Client and server The dynamic pass re-run against the new build, watching for any path that still leaves the device in the clear rather than re-testing only the one that did.
Decide ownership on the server Server The same request, the same session, an identifier belonging to another account, and a refusal. Re-run across the routes the template reached, not only the route it was found on.
The change a package-only report has no standing to ask for: no client-side control could have made this decision safely.
Authenticate the route the client never calls Server The request replayed with the session header removed, as at step five, and refused. The route table recovered from the build was used as the checklist, so the retest covered the routes nobody had traffic for.

Rotate the credential, then stop shipping it

Where
Server, then build
What confirmed it
Rotation confirmed against the server first, because a credential removed from the next build is still live until it is revoked. The new build was then decompiled again and the retest looked for the constant itself rather than for its effect.

Move the key off the client

Where
Server
What confirmed it
The payload field is produced where the key can be held. Confirmed by constructing the same request from the recovered key and having it refused.

Transport encryption on every call path

Where
Client and server
What confirmed it
The dynamic pass re-run against the new build, watching for any path that still leaves the device in the clear rather than re-testing only the one that did.

Decide ownership on the server

Where
Server
What confirmed it
The same request, the same session, an identifier belonging to another account, and a refusal. Re-run across the routes the template reached, not only the route it was found on.

The change a package-only report has no standing to ask for: no client-side control could have made this decision safely.

Authenticate the route the client never calls

Where
Server
What confirmed it
The request replayed with the session header removed, as at step five, and refused. The route table recovered from the build was used as the checklist, so the retest covered the routes nobody had traffic for.

How it ran

Autonomous, expert verified — and the one action that waited

The scope was authorised in writing across both classes, and the six phases ran from discovery through to the quality gate that runs on the finished report and can send it back. Nothing was deployed inside the customer’s network; application testing does not need it, and a deployment is required only for internal network work. One action in this engagement did not proceed on the platform’s own authority. Step five ends at a state-changing route, and anything that alters production state waits for written approval before it is performed — so the route was demonstrated as reachable without a session, and the state change itself was held at the gate until the customer approved it, with the request, the approval and the time it was given all recorded. Every finding on both halves was then verified by a senior Security Brigade auditor before the report was issued, which is what the expert-verified model is: the same run underneath, with a signature on top. The coverage does not change between delivery models. Only whose name the report goes out under does.

Measurement

What B-52 reached against our own assessment team

It belongs to the platform rather than to this engagement, and it is stated with what it is a proportion of.

B-52 run in parallel with Security Brigade’s expert assessment team As of 2026-09-15
  • B-52 and Security Brigade’s expert assessment team worked the same targets at the same time, and neither side saw the other’s output while the work was running.
  • Both sets of findings were pooled into a single denominator with each item counted once, so a defect both sides reached counts once rather than twice.
  • B-52 reached 90–95% of that pooled set. Part of what it reached was absent from the team’s own output, which is why the pooled set is larger than either side produced alone.
  • Every engagement Security Brigade has run since the firm started in 2006 was worked inside Lemon, and that record is what trained the models the platform runs on.

Deliberately excluded

  • It is a proportion of a pooled findings set. It is not a statement about this engagement, which has no coverage figure of its own.
  • Physical, hardware and wireless testing, which is out of scope for B-52 in every class.
  • Turnaround. The expert-verified model has no published turnaround figure, so none is stated.

Scope the binary and the interface as one engagement

Mobile applications and APIs are both coverage classes B-52 carries, in all three delivery models, and both are reachable from the self-serve flow. One scan is one application or one target and the entry price is $500, so a scope that takes in a client and the interface behind it is a scoping call rather than a single scan.