T09 · Insecure Skill Coding Practices
- Location
SKILL.md:847- Finding
Automatic Transmission of Potentially Sensitive Diagnostic Data Without User Consent
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is openly for remote Android control, but it asks for very sensitive device access and includes under-scoped automatic feedback, shell, and sideloading behavior users should review carefully.
Install only if you are comfortable giving Mobilerun remote control visibility into an Android device. Prefer a test or cloud device, avoid sensitive apps unless necessary, verify the Portal APK source independently, revoke Accessibility permission when done, and review any destructive action or feedback payload before allowing it.
SKILL.md:847Automatic Transmission of Potentially Sensitive Diagnostic Data Without User Consent
references/setup-and-billing.md:53Unverified APK Sideloading Followed by Granting Accessibility Service Privileges
references/troubleshooting.md:61Generic Device Shell Endpoint Expands Control Beyond the Documented Least-Privilege Interface
The activation trigger is extremely broad, covering essentially any request involving phones, automation, screenshots, reading screens, scraping, app testing, and AI agent tasks. That increases the chance the skill is loaded into contexts where invasive device control, data access, or destructive actions become available unnecessarily, expanding attack surface and likelihood of misuse.
The skill instructs the agent to always terminate cloud devices when done, including devices that may already exist and that the user may still want. Because DELETE is immediate and state-changing, this creates a meaningful risk of unintended service disruption, loss of session state, and unnecessary destructive actions without explicit confirmation.
**What to show the user:** Only report user-relevant device info: device name, state (`ready`/`disconnected`). Do NOT surface internal fields like `streamUrl`, `streamToken`, socket status, `assignedAt`, `terminatesAt`, or `taskCount` unless the user explicitly asks for technical details. If a device is `disconnected`, simply tell the user their phone is disconnected and ask them to open the Portal app and tap Connect. If they need help, walk them through the setup steps in [references/setup-and-billing.md](./references/setup-and-billing.md).
**Clean up cloud devices:** Cloud devices consume credits while running. Always terminate cloud devices (`DELETE /devices/{deviceId}`) when you're done using them -- don't leave them running. This applies whether you provisioned the device yourself or finished a task on an existing cloud device that the user no longer needs.
**Privacy:** Screenshots and the UI tree can contain sensitive personal data. Never share or transmit this data to anyone other than the user. Never print, log, or reveal the `MOBILERUN_API_KEY` in chat -- use it only for API calls.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
2. `GET /devices/{deviceId}/wait` -- wait until ready
3. `POST /tasks` with the new `deviceId` -- run the task (or submit multiple tasks -- they will queue and execute in order)
4. Monitor via `GET /tasks/{taskId}/status` until all tasks finish
5. `DELETE /devices/{deviceId}` -- terminate the device
**Important:** `DELETE /devices/{deviceId}` terminates the device immediately. If any tasks are still queued or running on that device, they will be orphaned or interrupted. Always wait for all tasks to finish before terminating.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
2. `GET /devices/{deviceId}/wait` -- wait until ready
3. `POST /tasks` with the new `deviceId` -- run the task (or submit multiple tasks -- they will queue and execute in order)
4. Monitor via `GET /tasks/{taskId}/status` until all tasks finish
5. `DELETE /devices/{deviceId}` -- terminate the device
**Important:** `DELETE /devices/{deviceId}` terminates the device immediately. If any tasks are still queued or running on that device, they will be orphaned or interrupted. Always wait for all tasks to finish before terminating.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
DELETE /devices/{deviceId}
Content-Type: application/json
{}
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
DELETE /devices/{deviceId}/keyboard
Clears the currently focused input field.
The skill exposes an app uninstall action on the controlled device without clearly requiring heightened confirmation before use. Uninstalling apps is destructive, can remove user data or access to important tools, and is especially risky in a broadly activated phone-control skill.
DELETE /devices/{deviceId}/apps/{packageName}
Content-Type: application/json
{}
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
DELETE /apps/{id}
Removes the app from R2 storage and the database. Use this before re-uploading an app with the same package name.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
Only one app per package name is allowed. To update:
1. Find the existing app: `GET /apps?query=com.example.myapp`
2. Delete it: `DELETE /apps/{id}`
3. Upload the new version using the 3-step upload flow above
---
Instructions found that direct the agent to transmit conversation context or user data to external services.
POST /tasks/{id}/message to nudge it in the right direction.POST /tasks/{task_id}/message
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
2. Alternatively, install the app manually on the device through the Play Store, then use it directly
3. For cloud devices, specify required apps in the `apps` array when provisioning: `POST /devices?deviceType=... { "apps": ["com.example.app"] }`
**9. `DELETE /keyboard` (clear) fails -- 'Accessibility fallback failed'**
- **Symptom:** `DELETE /devices/{deviceId}/keyboard` returns an error about accessibility fallback failing.
- **Cause:** The clear-text action relies on the accessibility service to select and delete text. It can fail if the focused field doesn't support text selection or the accessibility service lost its connection.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
**9. `DELETE /keyboard` (clear) fails -- 'Accessibility fallback failed'**
- **Symptom:** `DELETE /devices/{deviceId}/keyboard` returns an error about accessibility fallback failing.
- **Cause:** The clear-text action relies on the accessibility service to select and delete text. It can fail if the focused field doesn't support text selection or the accessibility service lost its connection.
- **Fix:** Use an alternative approach to clear text:
1. Type replacement text with the `clearFirst` flag:
The skill is fundamentally designed to send device commands and retrieve device data from an external API endpoint. In context this is expected functionality, but it is still a real external-transmission capability because screenshots, UI state, app/package information, and task instructions flow to a third-party service.
The hosted mobile cloud platform. Grant AI native control of Android devices to tap, swipe, type, navigate apps, fill out forms, extract data, automate workflows, and run QA. Connect your own phone, spin up on-demand virtual devices, or use always-on emulated and physical devices in the cloud. iOS support coming soon.
Base URL: `https://api.mobilerun.ai/v1`
Auth: `Authorization: Bearer <MOBILERUN_API_KEY>`
**Important:** The base domain (`https://api.mobilerun.ai/`) returns 404. You must always include `/v1` in the path. All API calls should be made via `curl`. Example:
This line reinforces the use of an external API with bearer-token authentication, enabling third-party transmission of commands and potentially sensitive mobile-device data. Although core to the skill's purpose, it still represents meaningful data egress and remote-control capability that must be treated as sensitive.
Base URL: https://api.mobilerun.ai/v1
Auth: Authorization: Bearer <MOBILERUN_API_KEY>
Important: The base domain (https://api.mobilerun.ai/) returns 404. You must always include /v1 in the path. All API calls should be made via curl. Example:
curl -s https://api.mobilerun.ai/v1/devices \
The example curl call demonstrates direct communication with the external Mobilerun service using the user's API credential. That creates a concrete path for off-platform transmission and remote actuation, which is sensitive even if intended.
Important: The base domain (https://api.mobilerun.ai/) returns 404. You must always include /v1 in the path. All API calls should be made via curl. Example:
curl -s https://api.mobilerun.ai/v1/devices \
-H "Authorization: Bearer $MOBILERUN_API_KEY"
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
The API key (MOBILERUN_API_KEY) is already available -- OpenClaw handles credential setup before this skill loads. Do NOT ask the user for an API key. Just use it.
Listing devices via the external API transmits account/device metadata to a third-party service and obtains inventory information about connected phones. In a phone-control skill, this is expected but still security-relevant because it exposes connected-device context and readiness for control.
curl -s https://api.mobilerun.ai/v1/devices \
-H "Authorization: Bearer $MOBILERUN_API_KEY"
state: "ready" = good to go, skip to the user's requestTaking screenshots through the external API is a genuine data-transmission risk because screenshots can contain highly sensitive personal information from the user's device. This is core functionality, but the sensitivity is elevated by the nature of the data being collected and transmitted.
curl -s https://api.mobilerun.ai/v1/devices/{deviceId}/screenshot \
-H "Authorization: Bearer $MOBILERUN_API_KEY" -o screenshot.png
The skill encourages the agent to proceed directly with device actions when a device is ready and emphasizes operational efficiency, but it does not consistently require user confirmation before destructive or high-impact operations like deleting cloud devices, uninstalling apps, typing into forms, or modifying settings. In a phone-control context, that can lead to unintended state changes or privacy-impacting actions without an adequate consent checkpoint.
The document tells the agent not to share screenshots or UI data with anyone other than the user, yet later instructs sending related task details to the platform via feedback. That inconsistency can cause privacy-sensitive device context to be disclosed under the guise of support/feedback, undermining the stated privacy boundary.
Fetching UI state from the external API transmits structured accessibility-tree data that may reveal screen contents, app structure, visible text, and interactive elements. In practice this can be as sensitive as screenshots and enables detailed remote observation of the device.
# Get all clickable/interactive elements
curl -s "https://api.mobilerun.ai/v1/devices/{id}/ui-state?filter=true" \
-H "Authorization: Bearer $MOBILERUN_API_KEY" | \
jq '[.a11y_tree | recurse(.children[]?) |
select(.isClickable==true or .isEditable==true) |
This UI-state example extracts content descriptions, which can expose labels and semantic information about the current screen to the external platform. That is intended functionality, but it materially increases observability into user activity and on-screen content.
{text: (.text // .contentDescription), bounds: .boundsInScreen, isEditable}]'
# Get elements with content descriptions (media items, icons, etc.)
curl -s "https://api.mobilerun.ai/v1/devices/{id}/ui-state?filter=true" \
-H "Authorization: Bearer $MOBILERUN_API_KEY" | \
jq '[.a11y_tree | recurse(.children[]?) |
select(.contentDescription != null and .contentDescription != "") |
Extracting editable fields from UI state can reveal draft text, form structure, and input targets on the user's device through the external API. That is a real privacy and integrity risk because it facilitates both observation and manipulation of sensitive inputs.
{desc: .contentDescription, bounds: .boundsInScreen, isClickable}]'
# Get editable fields only
curl -s "https://api.mobilerun.ai/v1/devices/{id}/ui-state?filter=true" \
-H "Authorization: Bearer $MOBILERUN_API_KEY" | \
jq '[.a11y_tree | recurse(.children[]?) |
select(.isEditable==true) | {text, resourceId, bounds: .boundsInScreen}]'
This example fetches only phone state and screen bounds, which is less sensitive than full UI trees or screenshots, but it still involves external transmission of device context. The context makes it less dangerous than the other E1 instances, though it remains part of the remote-observation surface.
select(.isEditable==true) | {text, resourceId, bounds: .boundsInScreen}]'
curl -s "https://api.mobilerun.ai/v1/devices/{id}/ui-state?filter=true"
-H "Authorization: Bearer $MOBILERUN_API_KEY" |
jq '{phone_state, device_context}'
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
Submit 2 tasks:
1. `"Open the Uber app, set the destination to 123 Main Street, select UberX, and stop before confirming -- report back the estimated price and arrival time"`
2. Only submit after reviewing the result of task 1 with the user — don't auto-confirm a purchase.
**Include safety conditions when appropriate:**
- `"If the app asks for login, stop and tell me"`
No suspicious patterns detected.