Skip to main content

ManifestTrace

tests python licence

Does an Android app's manifest leave something reachable that should not be.

This generalises two of this author's own disclosed CVEs into a scanner. CVE-2025-50861 was a single exported Android activity that could be reached without authentication. CVE-2025-50862 was android:allowBackup=true permitting the app's private data to be pulled over ADB backup. Both were found by hand, in one app, by reading its manifest. ManifestTrace reads the same signal, straight out of the compiled AndroidManifest.xml, across as many APKs as you point it at.

pip install manifest-trace
manifest-trace app.apk
manifest-trace ./apks/              # every .apk found under a folder

Why would anyone use this?

  • Mobile security researchers get a fast first pass across a batch of APKs for the exact bug class this author has already had assigned two CVEs for: unprotected exported components, open backups, debuggable builds, and plaintext network traffic by default.
  • Anyone auditing their own app's manifest gets the same check without installing the Android SDK or androguard.
  • People learning Android security get a small, readable reference for what a manifest actually controls, and a from-scratch reader for the binary XML format the manifest is compiled into, which most tools treat as a black box behind a heavier dependency.

What it is not: a decompiler, a dynamic analysis tool, or proof that a finding is exploitable. It reads what the manifest declares a component's exposure to be. Whether what happens once that component is reached is actually a problem needs a human to read the component's code. A finding here is a lead, not a report. Before acting on one, including against an app you did not expect to scan or one that turns out to belong to your own employer, read docs/VALIDATING.md: it covers whether you're authorised to go further, how to confirm each check by hand, and coordinated disclosure (ISO/IEC 29147) for anything found in someone else's app.

What it checks

Check What it looks for Generalises
exported_without_protection An activity, activity-alias, service or receiver reachable by any other app, with no permission and no signature check CVE-2025-50861
exported_provider_wide_open A content provider reachable by any other app, with no read or write permission and no per-path restriction the same bug class, for data providers
allow_backup_enabled android:allowBackup true, or left unset (which defaults to true) CVE-2025-50862
debuggable_true android:debuggable true in a shipped build a classic, unambiguous misconfiguration
cleartext_traffic_allowed Plaintext HTTP permitted, explicitly or by an old targetSdkVersion default a man-in-the-middle enabler

A component counts as exported if it is marked exported=true, or if exported is left unset and it has an intent-filter (the platform's own default), or, for providers only, if exported is unset and targetSdkVersion is below 17 (the old, implicit-export default that catches people who never even wrote exported=true). The one deliberate exception: the launcher activity (android.intent.action.MAIN / android.intent.category.LAUNCHER) is expected to be exported and is never flagged for that alone.

Install

pip install manifest-trace
# or: pipx install manifest-trace

Standard library only. No androguard, no Android SDK, no aapt.

Use

manifest-trace app.apk                   scan one APK
manifest-trace ./apks/                   scan every .apk found under a folder
manifest-trace app.apk --json            machine-readable output
manifest-trace ./apks/ --html report.html  a shareable report for a whole batch
manifest-trace app.apk --list-checks     every check, its severity and what it means
manifest-trace app.apk -q                just the verdict per APK

Exit codes: 0 clean, 1 at least one high or medium finding, 2 error (including a folder with no .apk files, or a file that is not a valid APK).

How it is tested

Two layers, the same split this author's other tools use. The binary XML reader (axml.py) is proven against hand-built compiled documents, byte for byte, so the format parsing itself is correct independent of any one real manifest. The checks (checks.py) are proven against fake manifests, one scenario per check that must fire, one clean scenario that must stay quiet. Neither of those needs a real APK and both run in CI on every commit.

Separately, the whole pipeline is run against two real, independently-built APKs: InsecureBankv2, a well-known, deliberately vulnerable training app, and a real, modern open-source app from F-Droid as a clean baseline. The tool correctly finds InsecureBankv2's documented exported-activity, exported-provider, allowBackup and debuggable issues without being tuned to that specific app, and does not invent findings on the clean sample that are not actually in its manifest. Not committed to the repository (APKs are large binaries); tests/fixtures/download.py fetches both on demand, and the tests that need them are skipped otherwise.

Run everything: python3 -m unittest discover -s tests -v. Real-APK tests first need python3 tests/fixtures/download.py (needs network, about 9 MB).

Known limitations

  • Manifest-level static analysis only. It does not decompile code, so it cannot tell you what an exported component actually does once reached, only that it is reachable.
  • It does not check code-level protections that never show up in the manifest: a component can declare no permission and still check the calling package or signature in its own code before doing anything sensitive. A finding here is a starting point for a manual read, not a conclusion.
  • allowBackup is checked as a flag only. A BackupAgent or fullBackupContent rule can legitimately narrow what actually gets backed up; this tool does not look that deep yet.
  • No deep link validation, no WebView-specific checks (addJavascriptInterface, loadUrl with untrusted input), no native library analysis. These are real, common Android bug classes this tool does not cover yet.
  • Tested against two real APKs so far, one old (targetSdkVersion 22) and one modern (targetSdkVersion 32+). If the binary XML reader behaves differently on an APK built by a toolchain neither of those represents, please open an issue with the APK's build tool version if you can share it: that is the most useful kind of report this project can get.

Credit and licence

Created and maintained by Jack Sessions. Parts of the code were written with AI assistance; every check is covered by the tests described above, and a finding is a lead to confirm, not proof.

MIT licence (see LICENSE). If you use ManifestTrace in a report, talk, course or another tool, please credit Jack Sessions and link https://github.com/JackSessions/manifest-trace (CITATION.cff has the details).

Metadata

Release files for manifest-trace 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for manifest-trace 0.1.0
File Size Uploaded
manifest_trace-0.1.0.tar.gz 27.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for manifest-trace 0.1.0
File Interpreter ABI Platform
manifest_trace-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 49.6 kB

Release files / manifest_trace-0.1.0.tar.gz

Download URL manifest_trace-0.1.0.tar.gz
Size 27.7 kB
Tags Source
SHA-256 checksum
How to use checksums
f072a43c045308ebdef5a9825847f61adab74a36733ed12382bd0508a9e0c435
BLAKE2b-256 checksum
How to use checksums
1b2268752eeee5d78073d3ed8b6cef011c16640e4d73f5784d8d8ca9a7b7797a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / manifest_trace-0.1.0-py3-none-any.whl

Download URL manifest_trace-0.1.0-py3-none-any.whl
Size 21.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1389f3b3efe2264c23ff96b54eedeb9abe25e41b0d90b9030a9fe53a4fbf8484
BLAKE2b-256 checksum
How to use checksums
18df0f4531647703c00bb4da8b7a3af4fd61ecf086c315de694ba259271f9506
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page