Skip to main content
What we test · Mobile binaries

The package tells you things the traffic never will

An intercepting proxy records one session: the routes that session took, the fields that session sent, the responses it happened to receive. A decompiled APK or IPA is not a record of a session at all. It is the instruction set — every endpoint the build names, every credential compiled into it, the pinning logic as written, and the exact shape of what the client was told to send. Some of that is reachable no other way. The most useful part of it is not a statement about the application.

Yash K · · What we test · about 12 min

The gap

Traffic is a record of one afternoon

Everything a proxy shows you is something the application decided to do while somebody was holding it. That is a narrower set than it looks.

Run a mobile application through an intercepting proxy and you get an honest, useful and strictly partial account: the routes exercised by the paths somebody happened to walk, as the account they walked them with, on the build installed that day, under whatever the server returned that morning. Nothing about it is wrong. What it does not contain is the rest — the administrative route the build still knows the address of, the second environment the client can be pointed at, the key that only travels when one particular flow is triggered, the parameter no screen renders and the parser still reads. None of that is hidden anywhere clever. It is compiled in, and the compiled artefact is the one thing an attacker is guaranteed to have, because a store handed it to them.

What comes out

Five things a package carries that a session does not

Each of these is recovered from the binary as published — signed, obfuscated, and with nothing switched off for the benefit of the test.

What is recoveredWhat the package showsWhy traffic does not
Secrets compiled in Keys, tokens and cryptographic material placed into the build at compile time, together with the class that reads them and the call that uses them. CWE-798 is use of hard-coded credentials; CWE-321 is use of a hard-coded cryptographic key. A secret that is never transmitted cannot be intercepted. One used to sign or encrypt locally never crosses the wire in a form anybody could pick out of a capture.
Endpoints nothing called Host names, path templates and route constants the binary names but the exercised flows never reach — a retired administrative route, a second environment, an older version of the interface the client can still speak. A proxy can only show a request that was made. A route nobody walked produces no traffic at all, and its absence from a capture is not evidence of anything.
Certificate pinning, as written The pin set, the place the check sits, what the failure path does, and whether every code path that opens a connection reaches the check at all. From outside, pinning presents as a refused connection, which is one bit of information. The code says which hosts are pinned, which are not, and what happens when a pin does not match.
Debug and logging paths Verbose logging still compiled into a release build, diagnostic screens behind a flag whose default is the only thing holding them shut, and test scaffolding that survived the build configuration meant to exclude it. These fire on a condition ordinary use does not meet — a flag, a build variant, a device property, an argument nobody passes by accident — so a trace of ordinary use records none of them.
What the client was told to send Serialisation classes, request builders, header construction and the parameters assembled before the first byte leaves the device, including every field the interface never exposes. Traffic shows the part of the contract the user interface chose to exercise. The builder shows the contract.
This is the row the second half of this article turns on.

Secrets compiled in

What the package shows
Keys, tokens and cryptographic material placed into the build at compile time, together with the class that reads them and the call that uses them. CWE-798 is use of hard-coded credentials; CWE-321 is use of a hard-coded cryptographic key.
Why traffic does not
A secret that is never transmitted cannot be intercepted. One used to sign or encrypt locally never crosses the wire in a form anybody could pick out of a capture.

Endpoints nothing called

What the package shows
Host names, path templates and route constants the binary names but the exercised flows never reach — a retired administrative route, a second environment, an older version of the interface the client can still speak.
Why traffic does not
A proxy can only show a request that was made. A route nobody walked produces no traffic at all, and its absence from a capture is not evidence of anything.

Certificate pinning, as written

What the package shows
The pin set, the place the check sits, what the failure path does, and whether every code path that opens a connection reaches the check at all.
Why traffic does not
From outside, pinning presents as a refused connection, which is one bit of information. The code says which hosts are pinned, which are not, and what happens when a pin does not match.

Debug and logging paths

What the package shows
Verbose logging still compiled into a release build, diagnostic screens behind a flag whose default is the only thing holding them shut, and test scaffolding that survived the build configuration meant to exclude it.
Why traffic does not
These fire on a condition ordinary use does not meet — a flag, a build variant, a device property, an argument nobody passes by accident — so a trace of ordinary use records none of them.

What the client was told to send

What the package shows
Serialisation classes, request builders, header construction and the parameters assembled before the first byte leaves the device, including every field the interface never exposes.
Why traffic does not
Traffic shows the part of the contract the user interface chose to exercise. The builder shows the contract.

This is the row the second half of this article turns on.

One finding, read three ways

A hard-coded key is three different findings

The same recovered constant means one thing to the engineer who shipped it, another to whoever is testing it, and a third to whoever owns the service at the other end.

01 Static

In the build

What is there
A constant and the class that consumes it, recovered from a signed release build with no source supplied and no unobfuscated variant requested.
What it is worth on its own
Not much. A compiled-in constant can be inert, and a finding that stops here is a code-quality observation wearing a severity rating.
02 Dynamic

In the run

What is tested
Whether the constant authenticates anything. It is used the way the application uses it, against the service the application uses it against, and what comes back is recorded.
What is produced
The request as sent, the response as returned, the steps that reproduce it, a CVSS v4.0 vector and a CWE — the artefact every B-52 finding carries, in every coverage class and in all three delivery models.
03 Consequence

On the server

What it says about the backend
A key that still works says the service accepts a credential distributed to every installation of the application. That is a finding about an interface, not about a handset.
Where it gets settled
Against the interface itself, on its own routes, with a credential for each role — which is a separate scope, and the reason the last section of this article exists.

The contract

What the client was told to send is how you learn what the server accepts

A request builder inside a package is a specification written by the same team that wrote the server.

Fields

Parameters no screen renders

A request object with members nothing populates is a member the server still parses. Sending it is the test. The builder is where you find out it exists to be sent.

Roles

Values the client is not meant to choose

Role names, tier identifiers and entitlement flags assembled on the device tell you what the server distinguishes between. Whether the server verifies the distinction, rather than trusting the client to make it, is the next request.

Versions

Interface versions the build still speaks

A client able to construct a request against an older route tells you that route was live when the build was cut. Whether it is still live, and still as permissive, is one request away.

Headers

Computed signatures, and how they are computed

Where a request carries a signature or an integrity header, the routine that produces it is in the package. Reproducing that routine is what makes the rest of the interface testable at all.

Environments

The other base address

A pre-production host compiled in beside the production one is ordinary. Whether the one that is not production is defended like production is a question the package raises and only a request answers.

Limits

Whatever the client checks before sending

Length caps, allowed character sets and range checks performed on the device are a written list of the assumptions the server may be making about its input. Each one is a test case for the server.

Release builds

Debug paths do not always leave with the debug build

This category survives for procedural reasons rather than technical ones.

Verbose logging is switched by a flag, the flag has a default, and the default lives in a file that is not the file anybody opens before a release. Diagnostic scaffolding is excluded by a build configuration, and that configuration stays correct right up until somebody adds a dependency that quietly pulls it back in. None of this shows in a session trace, because none of it fires under ordinary use — the condition is a flag, a build variant, a device property or an argument nobody passes by accident. All of it shows immediately in the package, because code is either in the binary or it is not, and that is a question with an answer rather than a probability. It is also where the two halves of a mobile assessment stop being separable: a diagnostic route reachable from a shipped client is not a property of the client. It is a route on somebody’s server, reachable by every copy of the application that was ever downloaded.

Coverage in MASVS terms

Eight categories, and where each answer actually lives

OWASP MASVS v2.1.0 carries eight categories and 24 controls, read on 8 September 2026. Verification levels went at v2.0.0 and became the MAS Testing Profiles, so coverage is stated by category. What a category list does not tell you is which of them a package can settle on its own.

CategoryWhere the answer livesWhat that means in practice
MASVS-STORAGE Package, then device What is written, where it is written and what protects it is decided by code in the build, and confirmed by what is actually sitting on the device after a session.
MASVS-CRYPTO Mostly the package Algorithm, mode and the origin of key material are all visible statically. A compiled-in key is identified here — and then followed to whatever still honours it.
MASVS-AUTH Both halves The client’s side of an authentication or authorisation flow is in the binary. Whether the server enforces the decision the client displays is not in the binary, and cannot be.
MASVS-NETWORK Package, then run Which hosts are pinned, where the check sits and what the failure path does are read from the code, and then exercised against the live connection.
MASVS-PLATFORM Package, then run Exported components, inter-process entry points and what the application will accept from another application on the same device — declared in the build, confirmed by sending it.
MASVS-CODE The package Dependencies, their versions and the data handling around them. A static question with a static answer, and one of the few here that needs nothing else.
MASVS-RESILIENCE The run Resistance to reverse engineering and tampering is measured by working against it rather than by reading a setting. The build arrives hardened and stays hardened for the test.
MASVS-PRIVACY Both halves Added at v2.1.0. What the client collects is in the package. What happens to it after transmission is a question for the interface that received it.

MASVS-STORAGE

Where the answer lives
Package, then device
What that means in practice
What is written, where it is written and what protects it is decided by code in the build, and confirmed by what is actually sitting on the device after a session.

MASVS-CRYPTO

Where the answer lives
Mostly the package
What that means in practice
Algorithm, mode and the origin of key material are all visible statically. A compiled-in key is identified here — and then followed to whatever still honours it.

MASVS-AUTH

Where the answer lives
Both halves
What that means in practice
The client’s side of an authentication or authorisation flow is in the binary. Whether the server enforces the decision the client displays is not in the binary, and cannot be.

MASVS-NETWORK

Where the answer lives
Package, then run
What that means in practice
Which hosts are pinned, where the check sits and what the failure path does are read from the code, and then exercised against the live connection.

MASVS-PLATFORM

Where the answer lives
Package, then run
What that means in practice
Exported components, inter-process entry points and what the application will accept from another application on the same device — declared in the build, confirmed by sending it.

MASVS-CODE

Where the answer lives
The package
What that means in practice
Dependencies, their versions and the data handling around them. A static question with a static answer, and one of the few here that needs nothing else.

MASVS-RESILIENCE

Where the answer lives
The run
What that means in practice
Resistance to reverse engineering and tampering is measured by working against it rather than by reading a setting. The build arrives hardened and stays hardened for the test.

MASVS-PRIVACY

Where the answer lives
Both halves
What that means in practice
Added at v2.1.0. What the client collects is in the package. What happens to it after transmission is a question for the interface that received it.

Where this comes from

What sits behind the two weakness classes named above

The two weakness classes, the framework versions behind the category table, and the artefact every finding arrives with.

Sourcing As of 2026-09-15
  • CWE-798, use of hard-coded credentials, and CWE-321, use of a hard-coded cryptographic key, are named here because each is recovered from a package rather than intercepted from traffic. That property is the argument of this article.
  • Framework versions — OWASP MASVS v2.1.0 with eight categories and 24 controls, and OWASP MASTG v2.0.0 for the test procedures behind them — were read on 8 September 2026 and carry that date wherever they appear on this site.
  • Every B-52 finding, in every coverage class and in all three delivery models, arrives with the request as sent, the response as returned, the steps that reproduce it, a CVSS v4.0 vector and a CWE.
  • Security Brigade has been running assessments since 2006, and every one of them was worked inside Lemon. That record is what the platform’s models were trained on.

Deliberately excluded

  • Physical, hardware and wireless testing, which is out of scope for B-52 in every coverage class.
  • Turnaround beyond one model: an observed median of one to three business days applies to the fully autonomous model. No equivalent figure exists for expert-verified or human-led work, so none is stated.

The payoff

The binary half and the API half are one engagement

A mobile test that stops at the package misses what the package tells you about the server.

Every item in this article points the same direction. A compiled-in key matters when a service still honours it. A route the running application never calls matters when the host still answers it. A parameter no screen renders matters when the parser still reads it. A signature routine matters because reproducing it is what makes the rest of the interface reachable. In each case the package supplies the question and the interface supplies the answer, and a report that delivers only the first half hands over a list of properties of a file. That is why these are scoped separately and worked together: one scan is one application or one target, and a client and the service behind it are two. B-52 covers both — along with the hosts that serve them and the source the build was compiled from — in all three delivery models. Fully autonomous, where signing off the scope is the last thing anybody is asked to do. Autonomous expert verified, where a senior Security Brigade auditor verifies every finding before it reaches you. Human led, where that auditor runs the engagement with the platform underneath. The coverage is identical in all three. What changes is whose signature the report carries.

Scope the binary and the interface as one engagement

One scan is one application or one target, and a mobile client and the service behind it are two. A single scan starts at $500 and a paid trial is $299. Anything wider than one target is a scoping call.