SECRET_KEY 为 Docker Compose 必填项,需使用唯一随机值;运行时测试需宿主机 ADB 可达,macOS 上 Docker Desktop 不会自动暴露 USB 设备;密钥候选完整值存于本地状态目录,需按敏感数据保护。
APKHunt
Cyber-BuddyGPL-3.0活跃维护基于 OWASP MASVS 框架的 Android 应用静态代码分析工具,帮开发者和安全测试人员快速发现并修复代码中的安全漏洞。
APKHunt is a comprehensive static code analysis tool for Android apps that is based on the OWASP MASVS framework. Although APKHunt is intended primarily for mobile app developers and security testers, it can be used by anyone to identify and address potential security vulnerabilities in their code.
export SECRET_KEY="$(openssl rand -hex 32)"
docker compose up --buildREADME 未说明显存或 GPU 要求;静态扫描、依赖清单、密钥审查与报告查看均不需要设备,运行时测试需连接并授权 Android 设备且容器可访问 ADB 服务。
本地 Android APK 静态分析工作台,按 OWASP MASVS 分组映射检查项并生成证据报告
基于 OWASP MASVS 框架的 Android 应用静态代码分析工具,帮开发者和安全测试人员快速发现并修复代码中的安全漏洞。
核心能力
- 用 JADX 反编译 APK,失败时回退 Apktool 提取清单与资源
- 将静态规则命中映射到 OWASP MASVS 分组并记录覆盖台账
- 用 Syft 生成 CycloneDX SBOM,并按版本化 PURL 查询 OSV
- 用 TruffleHog 扫描凭据候选,并在页面中按需展开
- 提供入口点图、威胁模型与 ADB 运行时启动验证工作台
容易踩的坑
- v2.0.0APKHunt | OWASP MASVS Android Static Analyzer最新正式版2026-09-24 · 2026-09-24 12:35 UTC
APKHunt | OWASP MASVS Android Static Analyzer

APKHunt now runs as a local web workbench for Android APK static security analysis. The original Go command-line scanner has been replaced on
main; the APKHunt name and OWASP MASVS focus continue.What changed
- Scan without blocking the interface. Upload an APK, follow the background worker, and revisit saved reports and scan history. JADX recovers Java/Kotlin source, with simplified and bounded per-DEX retries; Apktool supplies fallback manifest and resources.
- See what was actually checked. The coverage ledger records recovered files, rule evaluations, skipped files, and unresolved decompilation work. The scanner evaluates 38 active static signals plus one inventory-only rule; it does not claim complete code coverage.
- Review OWASP MASVS mapping honestly. The control page shows the scanner's state for all 24 current MASVS controls across eight groups, including missing checks. Static mapping is not a MASVS compliance verdict.
- Follow evidence beyond a finding list. Entry point graphs, a deterministic threat model, and context-specific runtime tests connect Android components with nearby source evidence and review questions. ADB tests require a reachable, authorized device.
- Inspect dependencies, routes, and secrets. Syft creates a CycloneDX inventory; OSV enriches versioned package identities when available. API routes are inventoried without contacting hosts during a scan. TruffleHog reviews recovered files and bounded APK content; provider verification and scoped route requests are opt-in.
Get started
Docker Desktop with Docker Compose v2 runs the scanner; the commands below also use Git and OpenSSL. No separate host installation of JADX, Apktool, Syft, or TruffleHog is needed. The image also includes curl and ADB.
git clone https://github.com/Cyber-Buddy/APKHunt.git cd APKHunt export SECRET_KEY="$(openssl rand -hex 32)" docker compose up --buildOpen
http://localhost:5005. The README screenshots show the scanner and each evidence page. Reports and worker state are stored in Docker named volumes.If you already cloned APKHunt, run
git pullin that checkout instead of cloning it again.Moving from the Go CLI
The old
go run apkhunt.go -p ...and-m ...commands are no longer present onmain. The original Go CLI remains in repository history. Existing CLI text reports are not imported into the web app.Reading results
Static matches are leads for review, not confirmed vulnerabilities. A JADX error can leave code paths unknown, an anonymous API response does not by itself prove an authorization flaw, and a secret candidate can be a false positive. APKHunt maps observations to OWASP MASVS; it does not certify an app or establish full compliance. See the MASVS control coverage audit for the exact implemented and missing checks.
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。

APKHunt | OWASP MASVS Android Static Analyzer
Apkhunt is a local Android APK static-analysis workbench. It extracts manifest and code signals, maps static checks to OWASP MASVS groups, captures a CycloneDX SBOM, and enriches versioned package identities through OSV when that service is available. It does not verify MASVS compliance.
Static matches are investigation targets, not proof of runtime reachability or exploitation.
Latest release: See the new web workbench and Go CLI migration notes.
Screenshots
Scan intake — choose an APK and start a background scan.

Saved report — review findings, severity, coverage, and dependencies in one place.

Coverage ledger
Scanned files, rule events, and unknown work.

Entry point graph
Components, handlers, and nearby calls.

Threat model
Trust boundaries and review questions.

Runtime tests
ADB readiness and component-specific tests.

API route evidence
Saved routes and scoped request controls.

Secret review
TruffleHog candidates and verification state.

The screenshots use a local InsecureBankv2 sample scan. Secret values remain collapsed, no API host is enabled for live tests, and static signals are not validated vulnerabilities.
Run with Docker
Requirements:
- Docker Desktop with Docker Compose v2
- A unique application secret
From this directory, start Apkhunt with:
export SECRET_KEY="$(openssl rand -hex 32)"
docker compose up --build
Open http://localhost:5005.
The Compose stack stores uploads, decompiled output, reports, scan history, and worker status in named Docker volumes. Stop it with docker compose down. Add --volumes only when you intentionally want to remove all saved scan data. An app restart interrupts a running worker; the restored status marks that scan as interrupted instead of claiming it is still running.
What a scan does
- Accepts an APK up to 200 MB by default and validates its ZIP structure before queuing a background scan. The page returns immediately; the scan status dock follows navigation across the app.
- Runs one scan at a time, uses JADX first, retries simplified JADX output after an auto-mode error, and retries bounded individual DEX files only if APK-level attempts leave no usable Java/Kotlin source. Per-DEX rescue uses
--show-bad-code; that flag is optional for the initial APK passes because it significantly slowed the reference APK without resolving its method errors. Apktool supplies fallback manifest and resources when JADX returns errors. The dock shows completed processing stages and elapsed time. When JADX emits work-unit progress, that percentage applies only to the current JADX attempt, not to the whole scan. - Evaluates structural manifest rules and the manifest-linked Network Security Configuration, then recursively walks recovered JADX files for static rules. It reads eligible text files up to 10 MB each; only Java, Kotlin, and XML currently have security rules. The report records scanned and skipped-file counts. Apktool fallback uses the manifest and selected resources; it also decodes Smali, whose file count is reported separately because Java/Kotlin rules do not inspect Smali instructions.
- Creates a CycloneDX SBOM with Syft when available.
- Queries OSV once for each versioned package URL and preserves unavailable or unknown states instead of inventing a severity.
- Saves a separate static API route inventory and a TruffleHog credential-candidate snapshot. Android XML namespace URLs are ignored; query strings and token-like path segments are removed from route evidence. No extracted host is contacted. TruffleHog does not verify with providers unless the upload explicitly opts in. The secret review page reveals full candidate values on request.
- Saves a coverage ledger with APK member extraction states, recovered-file rule events, skipped work, and decompiler attempts. It also saves a bounded entry point graph that connects manifest declarations to recovered handler-class evidence without claiming execution.
- Saves the report, evidence snapshots, and SBOM together. Opening a saved page never reruns decompilers, route extraction, TruffleHog, or OSV.
Follow-up workbenches
- Coverage ledger: inspect which archive members were copied, which recovered files and rules were evaluated, and which paths remain skipped or unknown. Listing limits and failed JADX attempts stay visible.
- Entry point graph: review exported components and deep links beside handler, permission-check, WebView, API, and sensitive-action evidence. Code in the same class is a lead, not a proven call path.
- Threat model: open an interactive map for a saved entry path, with Android trust boundaries, linked rule findings, exact source references, STRIDE review questions, a counter-hypothesis, and a path-specific proof step. The model is deterministic and uses no AI. Download its JSON for further review. Cytoscape.js is included locally under the MIT license.
- Runtime proof: see whether ADB is ready, then launch an explicitly exported activity from its saved graph entry. The workbench checks the installed base APK hash before launch and records the ADB result. This is shell-identity launchability evidence, not proof of an app-to-app vulnerability.
- API route evidence: choose one exact authorized hostname from source-code URL evidence, then run a bounded anonymous GET for its concrete HTTPS routes through curl. The same page saves status, response body, and digest. A 2xx response is labeled as responding without credentials, not as a confirmed authorization failure. The older manual comparison page remains available at its direct URL for saved cases.
Included coverage
The current rule set has 39 checks (38 active signals and one inventory-only rule) across storage, crypto, authentication, network, platform, code, and resilience-oriented Android surfaces. It includes review signals for manifest-linked cleartext and CA policy, expired certificate pins, unsafe WebView settings, FileProvider root paths, nested Intent forwarding, mutable PendingIntents, weak randomness, hardcoded keys, and AES-ECB use.
Every nontrivial static rule carries context checks and escalation conditions. Follow those before presenting a static signal as a vulnerability.
Android security coverage review and proposed feature sections records the current gaps, evidence limits, and build priorities. There are no active JavaScript or privacy rules in the rule engine. TruffleHog runs separately and reports candidates in the Secret review page.
MASVS control coverage audit maps all 24 current controls to implemented signals, inventory, and missing checks. The app exposes the same capability states at /masvs-coverage. No control is verified end to end by the current scanner.
Evidence and limitations
Apkhunt is static-first. The optional proof workbench records device state and user observations but does not independently establish runtime reachability, network transmission, an authorization failure, or exploitability. A validated conclusion still needs the exact APK, an independently observed consumer effect, and a causal negative control.
OSV enrichment is limited to saved, versioned package identities. A component without a versioned PURL is shown as not queryable; an unavailable OSV query is shown as not queried.
The API evidence page does not contact hosts during a scan or page view. Its opt-in route probe makes one scoped request; it does not establish intended access policy or object ownership. A URL in decompiled code may be unused or intentionally public. TruffleHog scans recovered code/resources plus bounded raw APK members and extracted binary strings; members over 64 MB or a 512 MB total unpack budget are recorded as skipped. Its verified state means the provider confirmed the credential at check time; it does not establish permissions or application impact. An unverified match can be a false positive. Full candidate values are stored in the local saved snapshot so they can be revealed in the UI; protect that state directory as sensitive data. Runtime observations and API response evidence are also stored under APKHUNT_STATE_DIR and are deleted with their scan.
Useful commands
docker compose up --build
docker compose logs --follow apkhunt
docker compose down
python3 -m pytest -q
The container runs as a non-root user and ships Syft 1.52.0, JADX 1.5.1, Apktool 2.10.0, TruffleHog 3.95.9, curl, and ADB. No separate host installation of those scan tools is needed. Compose binds the web UI to local loopback. Gunicorn uses one process with four request threads because the background queue and status are process-local.
Runtime tests require a connected, authorized Android device and an ADB server reachable from the container. Installing ADB in the image alone does not expose a macOS USB device to Docker Desktop. The static APK scan, dependency inventory, secret review, and saved report do not require a device.
Configuration
Environment variables:
SECRET_KEY— required by Docker Compose; use a unique random value.MAX_CONTENT_LENGTH— upload limit in bytes; defaults to209715200(200 MB).MAX_APK_ARCHIVE_MEMBERS— ZIP member cap; defaults to100000.MAX_APK_UNCOMPRESSED_SIZE— extracted-size cap; defaults to2147483648(2 GB).MAX_APK_COMPRESSION_RATIO— single-member compression-ratio cap; defaults to100.JADX_THREADS— JADX parallelism; Docker Compose uses4.DECOMPILER_TIMEOUT— Apktool time limit in seconds; defaults to1200(20 minutes).JADX_AUTO_TIMEOUT,JADX_SIMPLE_TIMEOUT— per-mode JADX limits in seconds; both default to600.JADX_STALL_TIMEOUT— seconds without an advance in JADX's reported work units before switching modes; defaults to180.JADX_SIMPLE_RETRY— retry simplified source recovery after auto mode returns errors; defaults totrue. Simplified output is labeled partial coverage in the saved report.JADX_SHOW_BAD_CODE— use MobSF's--show-bad-codeflag on APK-level JADX attempts; defaults tofalseafter a measured 299-second versus 102-second reference scan with the same 23 code errors and 9,500 rule-scanned Java/Kotlin files.JADX_PER_DEX_RETRY— if APK-level JADX leaves no source, retry up to 32 valid DEX members in isolated output directories; defaults totrue. These retries never replace usable whole-APK source because path-count differences do not prove additional class coverage.JADX_DEX_TIMEOUT,JADX_PER_DEX_BUDGET— per-DEX process limit (120 seconds) and total retry budget (600 seconds). Skipped members and recovered source counts are saved in the report.TRUFFLEHOG_TIMEOUT— seconds allowed for secret detection and optional provider verification; defaults to240.
Project history and license
This version replaces the original Go CLI with the local web workbench. The original CLI remains available in repository history. Apkhunt was originally developed by Sumit Kalaria and Mrunal Chawda.
The project is distributed under GPL-3.0. The bundled Cytoscape.js graph library retains its MIT license.