From workers-app-tester
Test Android apps on a rooted device. Decompile APKs, intercept traffic, parse UI, test for IDORs, bypass SSL pinning, hook methods with Frida, inspect exported components, read local storage, and find sensitive data. Use when asked to "test this app", "find bugs", "pentest", "reverse engineer", "decompile", "intercept requests", "check for IDORs", "bypass cert pinning", "hook this method", or "check deeplinks".
How this skill is triggered — by the user, by Claude, or both
Slash command
/workers-app-tester:workers-app-testerThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Pentest Android apps through a rooted device. Drives the device UI, intercepts network traffic, and uses Frida for runtime analysis.
Pentest Android apps through a rooted device. Drives the device UI, intercepts network traffic, and uses Frida for runtime analysis.
For detailed guides, load these on demand:
This workflow assumes the Android lab is already prepared:
adb shell settings get global http_proxy already points at port 18088C:\Users\emet\.mitmproxy\config.yamladb shell pm list packages -3
adb shell dumpsys activity activities | grep -m 1 -E 'topResumedActivity=|ResumedActivity:|mFocusedApp='
SESSION_DIR=/tmp/workers-app-tester-$(date +%Y%m%d-%H%M%S)
mkdir -p "$SESSION_DIR"
python3 scripts/mitm_watch.py verify
Expected:
18088su -c id returns uid=0If verification says the config is still bypassing everything, patch it before launching the app.
The capture helper now seeds hosts automatically from the installed package APK on the device. Start there before doing any manual host curation.
python3 scripts/mitm_watch.py start \
--session-dir "$SESSION_DIR" \
--package "<package>" \
--preserve-auth
What this does:
<package> from the deviceC:\Users\emet\.mitmproxy\config.yamlignore_hosts rule that bypasses everythingallow_hostsignore_hostsmitmdump in the background with capture.pyIf you already have extra hosts from reverse work, append them explicitly:
python3 scripts/mitm_watch.py start \
--session-dir "$SESSION_DIR" \
--package "<package>" \
--host "api.example.com" \
--host "auth.example.com" \
--preserve-auth
If APK seeding still looks incomplete, do a short census pass:
python3 scripts/mitm_watch.py start \
--session-dir "$SESSION_DIR" \
--package "<package>" \
--capture-all \
--preserve-auth
Exercise login/home/API-heavy paths for 1-2 minutes, then merge newly seen hosts from traffic:
python3 scripts/mitm_watch.py configure \
--traffic "$SESSION_DIR/traffic.jsonl"
adb shell am force-stop <package> || true
adb shell monkey -p <package> -c android.intent.category.LAUNCHER 1
Assume the proxy and certificate path are already correct. Missing HTTPS traffic now usually means SSL pinning. See references/frida.md — start frida-server, then spawn the app with bypass.js.
Emulator:
adb shell settings put global http_proxy 10.0.2.2:18088
Physical device:
adb shell settings put global http_proxy <host-ip>:18088
If the proxy is fine but config scope is wrong, patch only the monitored hosts:
python3 scripts/mitm_watch.py configure --host "api.example.com" --host "auth.example.com"
You can also rebuild the allowlist from APK or traffic evidence instead of typing hosts by hand:
python3 scripts/mitm_watch.py configure --package "<package>"
python3 scripts/mitm_watch.py configure --traffic "$SESSION_DIR/traffic.jsonl"
Dispatch to the reverse-agent with the package name and session directory. It will:
Returns: exported components, deeplink schemes, API endpoints, hardcoded secrets, security issues.
Use these findings to drive targeted testing in The Loop.
python3 scripts/ui.py
Returns a compact numbered list of interactive elements:
[1] "Sign In" btn @ (540,1200) bounds=[380,1150][700,1250] clickable
[2] "Email" input @ (540,400) bounds=[100,350][980,450] focusable
One action per cycle. Tap element [1]:
adb shell input tap 540 1200
For text fields, tap then type:
adb shell input tap 540 400
adb shell input text "[email protected]"
python3 scripts/traffic.py --input "$SESSION_DIR/traffic.jsonl" --since-seconds 15 --limit 10
With headers and bodies:
python3 scripts/traffic.py --input "$SESSION_DIR/traffic.jsonl" --since-seconds 15 --show-headers --show-body
After exercising the app's main flows, run the analyzer:
python3 scripts/analyze.py --input "$SESSION_DIR/traffic.jsonl" --mode full
Individual modes: endpoints, idor, auth, exposure, headers.
See references/testing-methodology.md for what to do with each finding.
| Action | Command |
|---|---|
| Tap | adb shell input tap <x> <y> |
| Type | adb shell input text "hello%sworld" (%s = space) |
| Scroll down | adb shell input swipe 540 1500 540 500 300 |
| Scroll up | adb shell input swipe 540 500 540 1500 300 |
| Back | adb shell input keyevent KEYCODE_BACK |
| Home | adb shell input keyevent KEYCODE_HOME |
| Enter | adb shell input keyevent KEYCODE_ENTER |
| Long press | adb shell input swipe <x> <y> <x> <y> 1000 |
| Launch app | adb shell monkey -p <pkg> -c android.intent.category.LAUNCHER 1 |
| Force stop | adb shell am force-stop <pkg> |
python3 scripts/mitm_watch.py stop --session-dir "$SESSION_DIR"
adb shell "su -c 'pkill frida-server'" 2>/dev/null || true
Do not clear the global proxy in a preconfigured lab unless you intentionally want to reset the device network path.
ui.py before acting so coordinates match the current screen.--capture-all census and immediately convert the observed hosts back into a narrower allowlist.sleep in any command. No sleep 1, no sleep 2, no sleep && command. Run commands directly. ui.py handles its own timing. Chain with && if needed.| Script | Purpose |
|---|---|
scripts/ui.py | Smart UI parser. Filters to interactive elements with spatial dedup. |
scripts/mitm_watch.py | Verify proxy/root/cert trust, patch config.yaml, and start/stop mitmdump. |
scripts/mitm_config.py | Shared host discovery and mitmproxy config helper used by mitm_watch.py. |
scripts/capture.py | mitmproxy addon. Logs to JSONL. Set PRESERVE_AUTH=1 to keep auth headers. |
scripts/traffic.py | Traffic viewer. --since-seconds, --show-headers, --show-body. |
scripts/analyze.py | Security analyzer. Modes: endpoints, idor, auth, exposure, headers, full. |
scripts/bypass.js | SSL pinning bypass. TrustManagerImpl, OkHttp3, SSLContext, Conscrypt. |
npx claudepluginhub daothinh/spec-cdex --plugin workers-app-testerGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.