T09 · Insecure Skill Coding Practices
- Location
bridge_daemon.py:648- Finding
Device-Control Entry Points Do Not Enforce the Documented User-Confirmation Boundary
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:267-273;ocr_bridge.py:323-334;bridge_daemon.py:648-658, 731-753
Vulnerability Type: Missing authorization enforcement for state-changing device actions
Risk Level: MediumRelevant Code
The Skill documentation requires confirmation before state-changing actions:
text - **Confirm before irreversible actions**: before submitting an order, a checkout step, or any tap that changes live app state, tell the user what will happen and wait for confirmation. Payment credentials (PIN, fingerprint) are ALWAYS entered by the user — scripts never request or store them.However, the primary OCR entry point immediately performs requested taps without requiring evidence of confirmation:
python elif cmd == "tap-text": text = rest[0] tap_text(text, idx=int(opt("--idx", 0)), x0=opt("--x0"), x1=opt("--x1"), y0=opt("--y0"), y1=opt("--y1")) for x in shot(): print(x) elif cmd == "tap": u2.connect().click(int(rest[0]), int(rest[1])) time.sleep(2.5) for x in shot(): print(x)The Appium backend similarly exposes state-changing handlers and executes them directly:
python ACTIONS = { "dump": cmd_dump, "tap": cmd_tap, "tap_bounds": cmd_tap_bounds, "tap_coords": cmd_tap_coords, "find": cmd_find, "scroll": cmd_scroll, "js_scroll": cmd_js_scroll, "screenshot": cmd_screenshot, "type": cmd_type, "wait": cmd_wait, "ocr_tap": cmd_ocr_tap, "find_book_button": cmd_find_book_button, }python action = sys.argv[1] args = {} if len(sys.argv) > 2: try: args = json.loads(sys.argv[2]) except json.JSONDecodeError: print(json.dumps({"ok": False, "error": "invalid json args"})) sys.exit(1) if _daemon_alive(): # Send command to daemon cmd = json.dumps({"action": action, "args": args}) _safe_write(CMD_FILE, cmd)Technical Analysis
The documented confirmat ...[truncated 2360 chars]
- Remediation
View remediation
Remediation Suggestions
- Require an explicit confirmation artifact for state-changing commands, rather than relying solely on agent instructions.
- Introduce a short-lived, single-use confirmation token bound to:
- the intended action;
- the target text, bounds, or coordinates;
- the active package and activity;
- an expiration time.
- Reject sensitive tap commands unless the caller provides a valid token generated after presenting the exact action summary to the user.
- Separate read-only and state-changing interfaces. Keep
dump,find,screenshot, and equivalent inspection commands available without confirmation, while gating click and typing operations. - Add a dry-run mode that resolves the target and returns the proposed coordinates and application context without sending input.
- Re-check the active package, activity, and target immediately before execution so a confirmation cannot be reused after the screen changes.
- Ensure dependent Skills cannot bypass the gate by invoking lower-level helpers such as
u2.connect().click()through an exposed wrapper. - Add automated tests verifying that all click-capable handlers reject execution when confirmation is absent, expired, mismatched, or already consumed.
