Where the logic actually lives
A React Native app is a native Android app with a JavaScript runtime embedded in it. The screens, the state and the request code are written in JavaScript, bundled into a single file that the runtime loads at start. The Java and Kotlin in the APK handle the runtime itself, the bridge, and any native modules the app depends on.
That layout changes the first question. Instead of reading classes, you locate the bundle, identify the JavaScript engine, and find the module that performs network calls. A release bundle is minified, so function names carry no meaning. A bundle compiled to Hermes bytecode is not text at all and needs a tool that understands the bytecode format before anything becomes readable.
What sits around the request
The bundle contains more than a URL list. Practical jobs usually need all of the following, and they are found in different places.
- The HTTP client the app uses. The built in fetch implementation and the XMLHttpRequest polyfill both route through the platform networking stack, while third party clients add their own configuration.
- The interceptor or wrapper that adds headers, a device value or a signature before the call leaves JavaScript.
- Configuration values such as the base URL per build, feature flags and API version, which are often selected at build time and baked into the bundle.
- Native modules that JavaScript calls, because a value produced there is invisible in the bundle even though the call site is not.
Read the bundle without reading everything
Bundle analysis scales badly if you start at the top. Start from a captured request instead.
- Take a distinctive string from the traffic, such as a path segment or a header value, and search the bundle for it.
- Follow the callers of the match. Minification preserves structure, so the shape of a function that builds a request object remains visible even when its name does not.
- Locate the point where the request object is finalized, which is where headers and signatures are attached.
When the bundle is Hermes bytecode, the same approach applies after disassembly. Strings and structure survive compilation, and the disassembly lists them in a form you can search. The output is closer to assembly than to JavaScript, so the goal is to identify data flow between a small number of functions rather than to recover the whole application.
Follow the bridge when the bundle stops
Some values cross into native code. When a signing routine is implemented as a native module, the bundle shows a call with arguments and a return value, and the algorithm is elsewhere.
Instrument both sides. On the JavaScript side, log arguments and results around the call. On the native side, work at the Java or Kotlin method that implements the module. Comparing the two views shows what changed in between, and it separates a value that JavaScript computed from one that the platform produced. From there the analysis continues in the compiled library, which is where JNI level work begins.
Verify the derivation rather than assume it
Reproducing a React Native request depends on getting three things right: the canonical string that is signed, the algorithm applied to it, and any header that the server also checks for consistency. Test each one against the running app.
- Hold every input constant and compare the app output with yours. Equality on one sample is weak evidence, so repeat with a changed body, a changed path and a changed timestamp.
- Where the outputs differ, vary one input at a time to find where your reading diverges.
- Send your version to the server and treat the response as the final test, since the server enforces the parts of the scheme the client only appears to enforce.
Deliver a client you can maintain
A React Native job usually ends with a portable client rather than with a patched bundle. The client implements the endpoints, the request shapes, the derived headers and the token flow in a language your team already runs, and it keeps its own tests against the live service. When the backend changes, you update the client by reading your own code instead of analysing the app a second time.
Related work
Reviewed 28 September 2026 · SReverse research desk