Back to skill

Security audit

Find My

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed local Find My automation tool, but it handles very sensitive location screenshots and broad UI clicks without enough containment.

Install only if you are comfortable giving the agent Screen Recording and Accessibility control over Find My and creating local screenshots of people, device, and item locations. Prefer setting FM_OUTPUT_DIR to a private directory, delete screenshots after use, avoid arbitrary coordinate clicks, and verify the selected Find My item before playing sounds or opening actions.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fm-screenshot.sh:7
Finding
Sensitive location screenshots are written to predictable temporary paths<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fm-screenshot.sh:7-23`; `scripts/fm-list.sh:11-25`; `scripts/fm-locate.sh:12-26`; `scripts/fm-play-sound.sh:50-52` **Vulnerability Type**: Unsafe temporary-file handling and insufficient protection of sensitive data **Risk Level**: Medium ### Vulnerable Code ```bash # scripts/fm-screenshot.sh:7-23 OUTPUT_PATH="${1:-/tmp/findmy.png}" # Set bridge socket path - expand $HOME if present in value PEEKABOO_BRIDGE_SOCKET="${PEEKABOO_BRIDGE_SOCKET:-\$HOME/Library/Application Support/OpenClaw/bridge.sock}" PEEKABOO_BRIDGE_SOCKET="${PEEKABOO_BRIDGE_SOCKET//\$HOME/$HOME}" export PEEKABOO_BRIDGE_SOCKET # Get window ID (--app flag hangs, so we use --window-id) window_id=$(peekaboo window list --app "Find My" --json 2>/dev/null | jq -r '(.data.windows[0].window_id // .windows[0].window_id) // empty') if [ -z "$window_id" ]; then echo "Error: Find My window not found. Is the app open?" >&2 exit 1 fi # Capture using window ID peekaboo image --window-id "$window_id" --path "$OUTPUT_PATH" 2>&1 ``` ```bash # scripts/fm-list.sh:11-25 OUTPUT_DIR="${FM_OUTPUT_DIR:-/tmp}" # Set bridge socket path - expand $HOME if present in value PEEKABOO_BRIDGE_SOCKET="${PEEKABOO_BRIDGE_SOCKET:-\$HOME/Library/Application Support/OpenClaw/bridge.sock}" PEEKABOO_BRIDGE_SOCKET="${PEEKABOO_BRIDGE_SOCKET//\$HOME/$HOME}" export PEEKABOO_BRIDGE_SOCKET # Switch to the requested tab "$SCRIPT_DIR/fm-tab.sh" "$TAB" >/dev/null 2>&1 sleep 0.3 # Capture screenshot timestamp=$(date +%s) output_path="$OUTPUT_DIR/findmy-${TAB}-list-${timestamp}.png" "$SCRIPT_DIR/fm-screenshot.sh" "$output_path" >/dev/null ``` ```bash # scripts/fm-locate.sh:12-26 OUTPUT_DIR="${FM_OUTPUT_DIR:-/tmp}" # Set bridge socket path - expand $HOME if present in value PEEKABOO_BRIDGE_SOCKET="${PEEKABOO_BRIDGE_SOCKET:-\$HOME/Library/Application Support/OpenClaw/bridge.sock}" PEEKABOO_BRIDGE_SOCKET="${PEEKABOO_BRIDGE_SOCKET//\$HOME/$HOME}" export PEEKABOO_BRIDGE_S ...[truncated 2744 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a private temporary directory atomically: ```bash umask 077 TEMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/findmy.XXXXXXXX") trap 'rm -rf -- "$TEMP_DIR"' EXIT OUTPUT_PATH="$TEMP_DIR/screenshot.png" ``` 2. Use `mktemp` for each generated screenshot rather than timestamp-only or fixed names. 3. Enforce restrictive permissions with `umask 077` and verify the generated file has mode `0600`. 4. Reject existing output destinations, symbolic links, directories, and non-regular files before invoking Peekaboo. 5. Canonicalize and validate `FM_OUTPUT_DIR`; require it to be owned by the current user and not writable by untrusted users. 6. Delete screenshots automatically after they have served their purpose unless the user explicitly requests retention. 7. If a user-provided persistent path is supported, clearly warn that it contains sensitive location information and avoid silently overwriting an existing file. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fm-click.sh:7
Finding
Relative-coordinate click helper permits clicks outside the Find My window<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fm-click.sh:7-39` **Vulnerability Type**: Insufficient coordinate bounds validation **Risk Level**: Medium ### Vulnerable Code ```bash REL_X="${1:?Usage: fm-click.sh <rel_x> <rel_y>}" REL_Y="${2:?Usage: fm-click.sh <rel_x> <rel_y>}" # Validate inputs are positive integers (prevent arithmetic injection) if ! [[ "$REL_X" =~ ^[0-9]+$ ]] || ! [[ "$REL_Y" =~ ^[0-9]+$ ]]; then echo "Error: Coordinates must be positive integers" >&2 exit 1 fi # Set bridge socket path - expand $HOME if present in value PEEKABOO_BRIDGE_SOCKET="${PEEKABOO_BRIDGE_SOCKET:-\$HOME/Library/Application Support/OpenClaw/bridge.sock}" PEEKABOO_BRIDGE_SOCKET="${PEEKABOO_BRIDGE_SOCKET//\$HOME/$HOME}" export PEEKABOO_BRIDGE_SOCKET # Get window bounds bounds=$(peekaboo window list --app "Find My" --json 2>/dev/null | jq -r '(.data.windows[0].bounds // .windows[0].bounds) // empty') if [ -z "$bounds" ]; then echo "Error: Find My window not found. Is the app open?" >&2 exit 1 fi win_x=$(echo "$bounds" | jq -r '.x') win_y=$(echo "$bounds" | jq -r '.y') # Calculate absolute coordinates abs_x=$((win_x + REL_X)) abs_y=$((win_y + REL_Y)) # Ensure Find My is focused and click peekaboo app switch --to "Find My" >/dev/null 2>&1 sleep 0.1 peekaboo click --coords "${abs_x},${abs_y}" 2>&1 ``` ### Technical Analysis The helper claims to click at coordinates relative to the Find My window. It validates only that both values consist of digits. It retrieves the complete window bounds but uses only the window's `x` and `y` origin; it never verifies that the supplied coordinates are less than the window's width and height. Consequently, sufficiently large values produce absolute coordinates outside Find My. Because Peekaboo operates with Accessibility permission, the resulting click may affect another application, system dialog, menu, Dock item, or desktop control visible at that screen position. Focusing Find My before clickin ...[truncated 1555 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse and validate all four window-bound fields: ```bash win_x=$(jq -r '.x' <<<"$bounds") win_y=$(jq -r '.y' <<<"$bounds") win_width=$(jq -r '.width' <<<"$bounds") win_height=$(jq -r '.height' <<<"$bounds") if (( REL_X < 0 || REL_X >= win_width || REL_Y < 0 || REL_Y >= win_height )); then echo "Error: Coordinates must be inside the Find My window" >&2 exit 1 fi ``` 2. Validate that all window-bound values are integers before arithmetic expansion. 3. Apply a narrower allowed region when the intended operation targets only the sidebar or tab bar. 4. Prefer window-scoped accessibility-element targeting instead of global screen-coordinate clicking. 5. Re-query the window bounds immediately before the click to reduce errors caused by movement or resizing. 6. Verify that the target window is still owned by Find My and remains frontmost before executing the action. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/fm-play-sound.sh:28
Finding
Broad accessibility keyword matching can activate unintended controls<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fm-play-sound.sh:28-40`; `scripts/fm-info.sh:22-35` **Vulnerability Type**: Ambiguous UI-element selection without identity or role verification **Risk Level**: Low ### Vulnerable Code ```bash # scripts/fm-play-sound.sh:28-40 result=$(peekaboo see --window-id "$window_id" --json 2>/dev/null) play_btn=$(echo "$result" | jq -r ' [.data.ui_elements // .ui_elements // [] | .[] | select(.is_actionable == true) | select(.label != null or .description != null) | select((.label // .description // "") | test("play|sound"; "i"))] | first // empty') if [ -n "$play_btn" ] && [ "$play_btn" != "null" ]; then play_id=$(echo "$play_btn" | jq -r '.id') echo "Found Play Sound button, clicking..." >&2 peekaboo click --on "$play_id" --window-id "$window_id" 2>&1 ``` ```bash # scripts/fm-info.sh:22-35 result=$(peekaboo see --window-id "$window_id" --json 2>/dev/null) # Look for info button (various possible labels) info_btn=$(echo "$result" | jq -r ' [.data.ui_elements // .ui_elements // [] | .[] | select(.is_actionable == true) | select(.description != null) | select(.description | test("info|detail|more"; "i"))] | first // empty') if [ -n "$info_btn" ] && [ "$info_btn" != "null" ]; then info_id=$(echo "$info_btn" | jq -r '.id') echo "Found info button, clicking..." >&2 peekaboo click --on "$info_id" --window-id "$window_id" >/dev/null 2>&1 ``` ### Technical Analysis Both scripts select the first actionable accessibility element matching broad regular expressions: - `play|sound` - `info|detail|more` The matching logic does not require an exact accessible name, expected role, expected location, or unique result. In `fm-play-sound.sh`, an element containing either “play” or “sound” is accepted rather than requiring the specific “Play Sound” action. In `fm-info.sh`, generic terms such as “more” can match unrelated controls. The scripts also do not confirm that ...[truncated 1356 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require exact, normalized accessible names such as `Play Sound` rather than matching either keyword independently. 2. Validate the accessibility role, for example requiring a button role where appropriate. 3. Collect all matches and fail safely if the result is ambiguous: ```bash matches=$(jq '[...]' <<<"$result") count=$(jq 'length' <<<"$matches") if [ "$count" -ne 1 ]; then echo "Error: Expected exactly one Play Sound button" >&2 exit 1 fi ``` 4. Verify the currently selected tab and item before performing the click. 5. Restrict candidate elements to the expected panel or approximate bounds when that metadata is available. 6. Require user confirmation before a consequential action such as playing a sound if the target identity cannot be reliably verified. 7. Treat accessibility-tree or localization changes as a safe failure rather than falling back to a broad first-match operation. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill is presented as a benign Find My controller, but its documented behavior includes capturing and storing screenshots of the Find My window, which can expose highly sensitive location data for people, devices, and items. That mismatch matters because users may authorize it for simple device-location tasks without realizing it persistently creates local image artifacts containing third-party and family location information.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script automatically captures and stores a screenshot of the Find My interface, which can expose precise location and address information for people, devices, or AirTags in a world-readable or weakly protected temporary directory. Because this happens without any confirmation, warning, minimization, or retention control, it creates a privacy-sensitive artifact that could be accessed by other local processes, users, logs, or later exfiltration paths.

Static analysis

No suspicious patterns detected.