Skip to main content

APK/IPA secret + endpoint scanner for vibe-coded mobile apps. Companion to Qualmly (qualmly.dev).

Project description

Qualmly Mobile Scanner — APK/IPA secret extraction

Single-file Python tool that unzips a packaged Android (.apk) or iOS (.ipa) build and scans every embedded text file for hardcoded secrets and backend URLs. Closes the function gap vs AuditYourApp's mobile reverse-engineering feature ($49/scan).

Status

Working v1. Run it on a real APK or IPA today. Catches ~80% of real-world secret leaks via plain-text grep at scale (which is how ~80% of secrets actually ship in mobile apps anyway).

What's done:

  • ✅ Auto-detects APK vs IPA format
  • ✅ Skips media/fonts/native libs (focuses on JS/JSON/plist/xml/config)
  • ✅ Same 9 secret patterns as the qualmly.dev Code Review (Anthropic, OpenAI, Stripe, AWS, GitHub PAT/classic, Slack, Google API, Supabase JWT)
  • ✅ Endpoint detection (Supabase, Firebase, localhost fallbacks)
  • ✅ Pretty-print + JSON output
  • ✅ Score + exit code (1 if any *_live secret found — useful for CI)
  • ✅ Stdlib only (zipfile + re); no install dependencies

What's NOT done (next iteration):

  1. Smali decompile for APK to reach obfuscated string constants. Add apktool integration. ~1 day.
  2. Mach-O binary string extraction for iOS apps where keys are baked into native binaries (not just JS bundles). Use nm or strings. ~1 day.
  3. Web upload UI — wrap as a Cloudflare Worker that accepts file upload, runs the same logic, returns a Qualmly-style report. Enables charging $9/scan via Stripe. ~2 days.
  4. Integration with qualmly.dev — add a "Mobile" mode tab next to App QA + Code Review. Could be a stub that links to the standalone scanner for now.

Install

# Recommended — installs into an isolated venv, exposes `qualmly-mobile` on PATH
pipx install qualmly-mobile

# Or vanilla pip if you prefer
pip install qualmly-mobile

No native dependencies. Stdlib only. Works on macOS, Linux, and Windows (Python 3.8+).

If you want to run from source instead, just clone this repo and call the script directly with python3 mobile-scanner/qualmly_mobile.py … — it has zero install dependencies.

Usage

# Scan an APK
qualmly-mobile /path/to/app.apk

# Scan an IPA
qualmly-mobile /path/to/MyApp.ipa

# JSON output for CI
qualmly-mobile app.apk --json

# Write JSON to file
qualmly-mobile app.apk --report scan.json

(If running from source: replace qualmly-mobile with python3 qualmly_mobile.py.)

Sample output:

  🔍 Qualmly Mobile Scan — myapp.apk
  ─────────────────────────────────────────────────
  Format:           APK
  Size:             14.2 MB
  Files scanned:    142 / 1387
  Score:            64/100  ██████░░░░
  Secrets found:    2
  Endpoints found:  4

  🔴 SECRETS:
     • Stripe publishable key             in  assets/index-Dp8DBQyP.js
       sample: pk_live_51TO… (107 chars total)
     • Supabase service-role JWT          in  assets/index-Dp8DBQyP.js
       sample: eyJhbGciOi… (240 chars total)

  🔵 ENDPOINTS:
     • Supabase project URL               →  https://abc1234567.supabase.co
       in assets/index-Dp8DBQyP.js
     • Localhost fallback                 →  http://127.0.0.1:3000
       in src/config.json
     ...

  Powered by Qualmly · qualmly.dev

Why a separate Python tool, not in the browser?

Two reasons:

  1. APK/IPA files are too big to upload to a browser-side scanner reliably. 50–500 MB is typical. A native CLI runs locally on the build artifact without uploading.
  2. CI/CD friendly. Drop into GitHub Actions / Bitrise / Codemagic. Exit code 1 fails the build on live keys.

A hosted version (web upload) is on the roadmap — that gets bundled into the Agency tier or charged $9/scan as a separate Mobile tier.

Roadmap

Phase Scope ETA after launch
v1 (this scaffold) CLI tool, secrets + endpoints — Ready to ship now
v1.1 apktool / smali integration for APK 1 week
v1.2 Cloudflare Worker hosted upload, $9/scan 2 weeks
v2 Mach-O binary scanner (iOS native), mobile-specific findings (root detection bypass, certificate pinning checks) 4–6 weeks

Publishing a new version (maintainer notes)

Releases are published to PyPI via GitHub Actions Trusted Publishing (OIDC) — no PYPI_API_TOKEN secret needed once the project is registered.

One-time setup on PyPI:

  1. Create the project skeleton: build + upload the first release with a manual API token (twine upload mobile-scanner/dist/*), OR pre-register it via Trusted Publishing's "pending publisher" flow at https://pypi.org/manage/account/publishing/ → add publisher with:
    • PyPI Project Name: qualmly-mobile
    • Owner: DarkPixel-Z
    • Repository name: qualmly
    • Workflow name: publish-mobile-pypi.yml
    • Environment name: pypi
  2. In the GitHub repo, create a pypi environment (Settings → Environments) so the workflow's environment: pypi clause resolves.

Cutting a release:

# bump __version__ in qualmly_mobile.py and version in pyproject.toml
git add mobile-scanner/qualmly_mobile.py mobile-scanner/pyproject.toml
git commit -m "mobile-scanner: bump to v1.0.1"
git tag mobile-v1.0.1
git push origin main --tags

The Publish qualmly-mobile to PyPI workflow fires on the tag, builds sdist + wheel, runs twine check, then uploads via OIDC.

License

MIT — same as the parent project.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qualmly_mobile-1.0.0.tar.gz (7.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qualmly_mobile-1.0.0-py3-none-any.whl (8.3 kB view details)

Uploaded Python 3

File details

Details for the file qualmly_mobile-1.0.0.tar.gz.

File metadata

  • Download URL: qualmly_mobile-1.0.0.tar.gz
  • Upload date:
  • Size: 7.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qualmly_mobile-1.0.0.tar.gz
Algorithm Hash digest
SHA256 f6d999e1fde14f2fb2f884ae2c7ffdf8e0081e651dadda0672cc13add6223747
MD5 26c2b87dbfd8f51683eff0b36058ace1
BLAKE2b-256 40a10b14b27d49df8122cb7216c65322c4920b755b7b56e72bcc45db6ce18df8

See more details on using hashes here.

Provenance

The following attestation bundles were made for qualmly_mobile-1.0.0.tar.gz:

Publisher: publish-mobile-pypi.yml on DarkPixel-Z/qualmly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file qualmly_mobile-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: qualmly_mobile-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 8.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qualmly_mobile-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d289ec6e67e7d4afac98e7c7c89b8924198f100b31a66a33e99f132783f2e95e
MD5 0dd458953ad5e624c23706957d57effa
BLAKE2b-256 7231fcb549d893d6f4492cbab40ffd15bdecf01db91647b8dc76186600c0cd21

See more details on using hashes here.

Provenance

The following attestation bundles were made for qualmly_mobile-1.0.0-py3-none-any.whl:

Publisher: publish-mobile-pypi.yml on DarkPixel-Z/qualmly

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page