hunting-hybrid-app-bundle-and-config-exposure · git:20260908.e3ae18a · 2026-09-08 · sha256 fd8658ccda8aa1ce
hunting-hybrid-app-bundle-and-config-exposure git:20260908.e3ae18aA
Immutable. This exact content is served forever at /api/v1/blob/fd8658ccda8aa1ce.
--- name: hunting-hybrid-app-bundle-and-config-exposure description: >- Hunt secrets and abusable configuration shipped inside a mobile app bundle, where the installable package carries hardcoded API keys, backend credentials, signing or encryption material, private endpoints, or feature and debug flags in its code, resources, web assets, or configuration files, so anyone who unpacks the distributed app recovers them, because the bundle is treated as private when a distributed binary is fully readable. Use when reviewing what a shipped mobile app package contains, including a hybrid app's embedded web assets and configuration. Covers hardcoded credentials and keys, embedded private endpoints, bundled web-asset secrets, and shipped debug or feature flags. The secret or abusable setting shipped in the bundle is the source, unpacking the distributed app is the sink, and recovering usable material or a privileged toggle from the package is the bug. license: MIT --- # Hunting hybrid app bundle and config exposure: when the shipped app carries its own secrets A mobile app is distributed as a package that lands on every user's device, and anyone can unpack it: the code, the resources, the embedded web assets of a hybrid app, and the configuration files are all readable. That is fine for everything a client is meant to hold, and a leak for anything that was meant to stay secret. Developers ship secrets into the bundle anyway, a backend API key hardcoded in the code, a credential in a resource file, signing or encryption material in the assets, a private internal endpoint in a configuration, or a debug or feature flag left enabled that unlocks privileged behavior. Because the app is treated as though its contents were private, these are shipped as if hidden, when in fact a distributed binary is fully readable. The bug is not that the app has configuration; it is a secret or an abusable setting that anyone who unpacks the package can recover and use. You hunt these by unpacking the shipped bundle and reading everything in it as an attacker would. ## When to use - A mobile app is distributed as a package whose code, resources, and configuration you can unpack. - A hybrid app embeds web assets and configuration files that may carry secrets or endpoints. - The bundle may contain hardcoded keys, credentials, private endpoints, or debug and feature flags. ## Scope check Hunt bundle exposure only on apps you own or are authorized to assess, unpacking a package you are permitted to analyze and proving any recovered secret is usable against test infrastructure rather than production. A recovered key or credential authenticates or unlocks a real service, so keep every probe within scope and treat recovered material as sensitive. If you can't name the authorization, stop. ## The loop 1. **Establish whether each recovered value is a live secret or an intended client value first.** For each secret-looking string, endpoint, or flag in the bundle, determine whether it is material meant to stay secret, a backend key, a credential, signing material, a private endpoint, or a privileged toggle, or a value a client is legitimately meant to hold, a public identifier or a scoped client token that grants nothing on its own. This is the false-positive killer: a public client identifier or a properly scoped token that authorizes nothing sensitive is not a finding even though it is in the bundle. Name what the value grants before claiming exposure. 2. **Unpack the bundle and enumerate its contents.** Extract the distributed package and list its code, resources, embedded web assets, and configuration files. For a hybrid app, include the bundled web assets and their configuration, which often carry endpoints and keys. 3. **Search for credential and key material.** Read the code, resources, and configuration for hardcoded API keys, backend credentials, signing or encryption keys, and tokens. Note each and what service or capability it would authenticate to. 4. **Search for private endpoints and settings.** Read the configuration and assets for internal or private endpoints, hosts, and service addresses the app talks to, and for feature or debug flags that unlock behavior a production user should not have. 5. **Check what each recovered value grants.** For each secret, endpoint, or flag, determine whether it is usable, whether the key authenticates to a live service, the endpoint is reachable, or the flag actually enables privileged behavior when set, so the exposure has real impact rather than being an inert artifact. 6. **Confirm and record.** Confirm by using a recovered secret or setting against test infrastructure you are permitted to reach, showing the key authenticates, the private endpoint responds, or the flag unlocks behavior, without acting against production. Kill the lead if every recovered value is a public client identifier or a scoped token that grants nothing sensitive, if endpoints are public, and if flags do not enable privileged behavior. Record the value, where in the bundle it was found, what it grants, and the proof, or set a `kill_reason`. ## Where bundle exposure leaks - **What the value grants is the finding.** A distributed bundle is fully readable; the bug is a value in it that grants something sensitive, not merely a string that looks secret. Name what it unlocks. - **Hardcoded backend keys are live.** An API key or credential compiled into the code or a resource authenticates to the backend for anyone who extracts it, so the client is not a safe place to keep it. - **Hybrid web assets carry endpoints and keys.** A hybrid app's embedded web assets and their configuration often hold service endpoints and keys in plain view, unpacked with the rest of the bundle. - **Private endpoints are disclosed by shipping them.** An internal host or service address in the configuration is revealed to anyone who reads the bundle, mapping the backend for an attacker. - **Shipped debug and feature flags unlock behavior.** A debug mode or feature flag left enabled, or settable, in the bundle can unlock privileged behavior a production user should never reach. ## Worked example (a confirm and a kill) > **Confirm.** A hybrid app's embedded web-asset configuration contains a backend API key and a private > administrative endpoint. Extracting the bundle recovers both, and the key authenticates to the endpoint on > test infrastructure, granting access a client should not have. **Confirmed** secret and private-endpoint > exposure in the shipped bundle, `high`, remediation = remove backend keys and private endpoints from the > bundle, have the client obtain scoped short-lived tokens from an authenticated service, and gate privileged > endpoints server-side rather than by a shipped key. > > **Kill.** The same bundle contains only a public client identifier and a token scoped so it authorizes > nothing without a server-side session, the endpoints in the configuration are the public API, and no debug > or feature flag in the bundle enables privileged behavior. Every recovered value grants nothing sensitive on > its own. **Killed**, `kill_reason` = "the bundle carries only a public identifier and a scoped token that > authorizes nothing alone, public endpoints, and no privileged flag; nothing recovered from the package grants > sensitive access." ## Rationalizations to reject - *"The key is inside the compiled app."* -> A compiled app is unpacked and read routinely; compilation is not concealment, so a key in the binary is a published key. - *"It is only used by our own app."* -> Anyone who extracts the bundle can use the same key or endpoint; the client cannot enforce that only the genuine app holds it. - *"That endpoint is internal."* -> Shipping its address in the bundle discloses it, and if it is reachable the disclosure maps the backend; confirm reachability rather than assuming internal means hidden. - *"The debug flag is off by default."* -> If it is settable in the bundle or the configuration, an attacker on a controlled device can turn it on; confirm the privileged behavior is gated server-side, not by a flag. - *"It is just an obfuscated string."* -> Obfuscation slows recovery, it does not prevent it; treat an obfuscated live secret as exposed. ## Executing this in practice You need the unpacked bundle with its code, resources, embedded web assets, and configuration, every secret-looking value, endpoint, and flag in it, and for each what it authenticates to or unlocks. For each, decide whether it is a live secret, a reachable private endpoint, or a privileged flag, or an inert client value. Reading the unpacked contents settles most leads; using a recovered value against permitted test infrastructure to show it grants sensitive access settles the rest. ## Related - `hunting-mobile-secret-and-storage-exposure` - the runtime and at-rest secret hunt, of which a secret compiled into the shipped bundle is the build-time case. - `auditing-mobile-backend-and-firebase-exposure` - a backend key or endpoint recovered from the bundle feeds directly into the backend exposure that skill audits. - `hunting-firmware-secrets-and-debug-interfaces` - the embedded-device analogue, where secrets and debug interfaces ship inside a readable firmware image. - `hunting-mobile-tls-pinning-and-trust-gaps` - a private endpoint disclosed by the bundle is reached over a connection whose transport trust that skill audits. - [FINDING-SCHEMA.md](../../FINDING-SCHEMA.md) - source = the secret or abusable setting shipped in the bundle, sink = unpacking the distributed app, evidence = a recovered secret authenticating, a private endpoint responding, or a flag unlocking behavior on test infrastructure.