Skip to Content
Alpha — full Android pipeline + iOS toolkit + live dynamic loop. API still shifting; pin to commits in CI.
WorkflowsAndroid static scan

Android static scan

The bread-and-butter workflow. APK in → findings + attack surface + auto-generated Frida hooks out.

The one-liner

mnexus scan ./target.apk

Everything below is what just happened and how to tune it.

Pipeline

target.apk ├─→ apktool extract_manifest ←─ package + version + permissions ├─→ apktool decode (smali) ←─ smali tree under workspace/<pid>/smali/ ├─→ jadx decompile ←─ java tree under workspace/<pid>/java/ ├─[fan-out in parallel]─→ │ ├─ secrets_detector ─→ FIND-* (HIGH/CRITICAL with mitigation) │ ├─ deeplink_extractor ─→ AttackSurface.deeplinks │ ├─ permission_analyser ─→ AttackSurface.permissions │ ├─ crypto_primitive_sniffer ─→ AttackSurface.crypto_ops │ ├─ ghidra_engine (native libs)─→ JNI exports + ROP gadgets + URL refs │ ├─ mobsf_engine (if running) ─→ second-opinion findings │ └─ pinning_lib_detector ─→ AttackSurface.pinning_strategies ├─→ correlator ─→ static-suspicion + evidence merge └─→ hook_generator ─→ workspace/<pid>/hooks/*.js (Frida)

Engines that participate

apktool, jadx, ghidra (if installed), mobsf (if running), frida (auto-hook generator only — runtime is opt-in via Dynamic →), plus a handful of in-tree detectors in mnexus/intelligence/.

Engines you can skip: ghidra is the biggest one. Without it the Native tab will only show what apktool could extract (basic symbol names from .dynsym, plus strings-style URL refs). For most Android apps that’s enough.

CLI

mnexus scan ./target.apk \ --package com.target.app \ # override auto-detect --version 4.2.1 # override auto-detect

REPL equivalent:

🔱 nexus ❯ /scan ./target.apk

Both end up calling MedusaNexus.ingest_apk() — the same code path as POST /v1/apks/upload.

What the web UI gives you

Open http://127.0.0.1:8765/#/projects/PRJ-… after /serve:

TabBacking endpointWhat you see
FindingsGET /v1/projects/{id}/findingsEvery finding, filterable by severity / category.
SecretsGET /v1/projects/{id}/secretsConfirmed + suspected. Distinct from generic findings because the false-positive rate is high enough to warrant manual review.
ComponentsGET /v1/projects/{id}/componentsExported activities / services / receivers / providers + their intent filters.
NativeGET /v1/projects/{id}/nativePer-.so: JNI exports, hardcoded URLs, crypto routines, exported functions.
API mapGET /v1/projects/{id}/api-mapStatic URL extraction. When Moxy is up, gets a live hits overlay.
SSL mapGET /v1/projects/{id}/ssl-mapPinning libs detected → matching bypass recipes pre-wired.
OWASPGET /v1/projects/{id}/owaspM1–M10 MASVS matrix.
Attack treeGET /v1/projects/{id}/attack-treeDAG view of attacker → asset chains.
DataflowGET /v1/projects/{id}/dataflowSource → sink (crypto + network).
SurfaceGET /v1/projects/{id}/surfaceRaw AttackSurface model dump for power users.
HooksGET /v1/projects/{id}/hooksAuto-generated Frida scripts, ready to load.
CorrelationsGET /v1/projects/{id}/correlationsStatic suspicion + dynamic evidence pairs.
TrafficGET /v1/projects/{id}/trafficMITM capture (proxy plugged in).
Manifest diffGET /v1/projects/{id}/manifest-diffSurface delta vs prior scan.
Findings diffGET /v1/projects/{id}/findings-diffSecurity delta vs prior scan.

Re-scanning

When you suspect a finding is stale (e.g. you changed a rule):

🔱 nexus PRJ-… ❯ /rescan

This re-runs the pipeline in place — the same PRJ-… id, same DB row, fresh findings. Use this when:

  • You edited rules under rules/.
  • You upgraded an engine and want to confirm.
  • You want to drop a finding that was a false positive.

To compare two builds of the same app (where version actually changed), re-scan the new APK as a new project with mnexus scan — the diff endpoints auto-pick the latest prior scan of the same package.

Dedup is on by default — uploading the same APK bytes twice returns the existing project id. Override with force=true on the /v1/apks/upload endpoint or --force on the CLI.

Common pitfalls

SymptomLikely cause
apktool errors with “Could not decode arsc file”Modern AAPT2 compact resources. The orchestrator falls back to filename heuristics; findings still land.
jadx runs foreverHeavy ProGuard’d APK. Pass --no-jadx (CLI flag coming) or let it run — it’s not blocking the rest of the pipeline.
Zero secrets foundThe detector defaults to conservative patterns. Look in mnexus/playintel/secret_detector.py to tune.
Native tab emptyNo lib/*/, or the .so was packed. Ghidra still tries — check ghidra_engine logs in the workspace.
Risk score feels wrongmnexus/intelligence/risk_score.py — pure function, easy to tune.

Next: drive a Frida session against the same project → Dynamic + Frida.