Back to skill

Security audit

Mac Control

Security checks for vulnerabilities and agentic risk

Overview

The skill broadly matches its Mac UI automation purpose, but it needs Review because its scripts can generate real clicks, capture screens, leave screenshots behind, and contain an AppleScript injection flaw.

Install only if you are comfortable granting an agent practical control over your Mac UI and screen contents. Use it for tightly scoped, user-directed automation, avoid passing untrusted application names into its scripts, and treat screenshots saved under /tmp or calibration files under ~/.clawdbot as potentially sensitive. The package should be reviewed or hardened before use on accounts that handle private, financial, administrative, or security-sensitive workflows.

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

Error
Location
scripts/get-window-bounds.sh:24
Finding
AppleScript Injection Through an Untrusted Application Name<![CDATA[ ## Vulnerability Details **File Location**: `scripts/get-window-bounds.sh:24-33` **Vulnerability Type**: AppleScript injection leading to arbitrary local command execution **Risk Level**: High ### Vulnerable Code ```bash osascript -e " tell application \"System Events\" tell process \"$APP_NAME\" set win to front window set {x, y} to position of win set {w, h} to size of win end tell end tell return \"x:\" & x & \" y:\" & y & \" width:\" & w & \" height:\" & h " ``` ### Technical Analysis The script directly interpolates the first command-line argument, stored in `APP_NAME`, into dynamically generated AppleScript source. Shell double-quote escaping only preserves the surrounding shell string; it does not escape the value for the AppleScript language. An application name containing quotation marks and additional AppleScript statements can terminate the intended `tell process` string and alter the program parsed by `osascript`. An injected statement could invoke AppleScript capabilities such as `do shell script`, resulting in arbitrary command execution. The vulnerability becomes exploitable whenever an untrusted user, external task, or manipulated Agent instruction can influence the application-name argument passed to this script. ### Attack Path 1. An attacker supplies or influences the application name requested by an automation task. 2. The Agent invokes `scripts/get-window-bounds.sh` with the attacker-controlled value as its first argument. 3. The script inserts that value directly into the AppleScript source at line 26. 4. Embedded quotation marks terminate the intended process-name string. 5. Additional attacker-controlled AppleScript statements are parsed by `osascript`. 6. The injected statements execute with the privileges and macOS permissions of the process running the Skill. ### Impact Assessment Successful exploitation permits arbitrary local command execution under the account running the Agent. T ...[truncated 474 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not construct AppleScript source by interpolating command-line values. Pass the application name as an argument to `osascript` and retrieve it from an `on run argv` handler: ```bash osascript - "$APP_NAME" <<'APPLESCRIPT' on run argv set appName to item 1 of argv tell application "System Events" tell process appName set win to front window set {x, y} to position of win set {w, h} to size of win end tell end tell return "x:" & x & " y:" & y & " width:" & w & " height:" & h end run APPLESCRIPT ``` Additional hardening should include: 1. Reject empty values and values containing control characters. 2. Compare the requested name against the names of currently running application processes. 3. If the expected applications are known, enforce a strict allowlist. 4. Return an error when the application does not exist rather than attempting to reinterpret the input. 5. Add regression tests using names containing quotes, backslashes, line breaks, and AppleScript keywords. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/calibrate.sh:7
Finding
Predictable Temporary Directory Used for Calibration Screenshot<![CDATA[ ## Vulnerability Details **File Location**: `scripts/calibrate.sh:7-9, 22-23, 71-72` **Vulnerability Type**: Predictable temporary path and insufficiently protected screenshot storage **Risk Level**: Medium ### Vulnerable Code ```bash CALIBRATION_FILE="$HOME/.clawdbot/mac-control-calibration.json" TMP_DIR="/tmp/mac-calibrate-$$" mkdir -p "$TMP_DIR" mkdir -p "$(dirname "$CALIBRATION_FILE")" ``` ```bash # Capture screenshot with cursor /usr/sbin/screencapture -C -x "$TMP_DIR/cursor.png" ``` ```bash # Cleanup rm -rf "$TMP_DIR" ``` ### Technical Analysis The script builds its temporary directory name from the process ID and creates it with `mkdir -p`. Process identifiers are predictable, and `mkdir -p` does not guarantee that the directory was created atomically by the current process. The script also does not set a restrictive `umask`, validate ownership of an existing directory, or reject symbolic-link-based path manipulation. A local attacker may predict or race the path and pre-create the directory or controlled entries within it. The screenshot written to `cursor.png` may contain sensitive information visible on the user’s display. Although the directory is removed at the end of normal execution, cleanup is not registered through a signal trap. A failure, interruption, or forced termination before line 72 can leave the screenshot behind. ### Attack Path 1. A local attacker predicts or observes the process ID that will be used by the calibration script. 2. The attacker pre-creates `/tmp/mac-calibrate-&lt;pid&gt;` or races directory creation. 3. The script accepts the existing path because it uses `mkdir -p`. 4. The screenshot command writes `cursor.png` into the attacker-influenced location. 5. The attacker reads the screenshot or manipulates the destination before cleanup. 6. If the script terminates abnormally, the captured image may remain in `/tmp`. ### Impact Assessment The primary impact is local disclosure of screen contents, potent ...[truncated 414 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Create the temporary directory atomically with restrictive permissions and register cleanup immediately: ```bash umask 077 TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/mac-calibrate.XXXXXX")" || { echo "Unable to create a secure temporary directory" >&2 exit 1 } trap 'rm -rf -- "$TMP_DIR"' EXIT HUP INT TERM ``` Additional hardening should include: 1. Verify that screenshot creation succeeds before processing the image. 2. Avoid `mkdir -p` for security-sensitive temporary directories. 3. Quote all references to temporary paths. 4. Keep screenshots only for the minimum time necessary. 5. Ensure the calibration directory under the user’s home directory is also created with user-only permissions where appropriate. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/find-element.sh:7
Finding
Predictable Temporary Directory and Persistent Full-Screen Capture<![CDATA[ ## Vulnerability Details **File Location**: `scripts/find-element.sh:7-8, 46-48, 77-88` **Vulnerability Type**: Unsafe temporary-file handling and residual sensitive screenshots **Risk Level**: Medium ### Vulnerable Code ```bash TMP_DIR="/tmp/mac-find-element-$$" mkdir -p "$TMP_DIR" ``` ```bash # Take screenshot with cursor /usr/sbin/screencapture -C -x "$TMP_DIR/full.png" echo "Screenshot saved: $TMP_DIR/full.png" ``` ```bash # Use sips to crop # sips crops from top-left, we need to calculate properly sips -c $CH $CW --cropOffset $CY $CX "$TMP_DIR/full.png" --out "$TMP_DIR/cropped.png" 2>/dev/null echo "Cropped image: $TMP_DIR/cropped.png" echo "" echo "To view: open $TMP_DIR/cropped.png" echo "Full screenshot: $TMP_DIR/full.png" # Output paths for scripting echo "FULL=$TMP_DIR/full.png" echo "CROPPED=$TMP_DIR/cropped.png" ``` ### Technical Analysis The script uses a predictable process-ID-based path under the shared `/tmp` directory and creates it with `mkdir -p`. It does not atomically establish directory ownership, set a restrictive `umask`, or verify that the path was not created by another local user. The script captures the entire screen into `full.png` and creates an additional cropped image. Unlike the calibration script, it provides no cleanup operation or expiration mechanism. Both images remain in the temporary directory after the script exits. The combination of predictable naming and retained full-screen captures increases the opportunity for local information disclosure. A local attacker may pre-create or race the directory and then access the resulting images. Even without active exploitation, residual screenshots can remain readable longer than required. The unquoted numeric crop arguments at line 79 also lack validation, but the confirmed security exposure is the unsafe storage and retention of screenshots. ### Attack Path 1. A local attacker predicts or observes the PID-derived directory name. 2. The attacker creates `/ ...[truncated 1067 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Use an atomically created, user-private temporary directory: ```bash umask 077 TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/mac-find-element.XXXXXX")" || { echo "Unable to create a secure temporary directory" >&2 exit 1 } trap 'rm -rf -- "$TMP_DIR"' EXIT HUP INT TERM ``` If retaining screenshots is a required feature, use an explicit opt-in option instead of retaining them by default: 1. Delete full and cropped screenshots automatically when the script exits. 2. Add a `--keep` or `--output-dir` option for intentional retention. 3. Require any caller-provided output directory to be owned by the current user and not writable by other users. 4. Create retained files with user-only permissions. 5. Warn users that full-screen captures may contain sensitive information. 6. Validate `CX`, `CY`, `CW`, and `CH` as non-negative integers and quote them when passing them to `sips`. 7. Check the exit status of `screencapture` and `sips` before printing output paths. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description is focused on Mac UI automation and interaction with on-screen elements through mouse/keyboard automation tools. The supplied code does not perform any UI automation at all. Instead, it implements offline image processing: it takes an input image, checks dimensions, copies it, and crops a region using sips. While image cropping could conceivably support screenshot workflows, this code chunk’s primary behavior is file-based image manipulation, which is a materially different capability from the declared purpose and omits the core declared behaviors entirely.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill performs direct mouse and keyboard automation, including clicking dialogs, typing text, and activating focused elements, but does not prominently warn that synthetic input can trigger unintended or irreversible UI actions. In this context, a missed target, stale coordinates, or focus change could approve prompts, submit forms, close windows, or alter settings unexpectedly.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill performs direct mouse and keyboard automation, including clicking dialogs, typing text, and activating focused elements, but does not prominently warn that synthetic input can trigger unintended or irreversible UI actions. In this context, a missed target, stale coordinates, or focus change could approve prompts, submit forms, close windows, or alter settings unexpectedly.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The header comments and progress messages describe this as a calibration routine that discovers the real coordinate scale factor through screenshot-based analysis. However, the image-analysis steps are not implemented, and L45 hard-codes SCALE_FACTOR="2.5", meaning the script does not do what its documentation says it does.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script captures a screenshot with the cursor and persists calibration data to the user's home directory without any explicit notice, consent flow, or minimization of what may be captured. In the context of a UI automation skill, screenshots can contain sensitive on-screen information from unrelated apps, making silent capture and storage a meaningful privacy risk even if the immediate script intent appears operational rather than malicious.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script directly invokes cliclick to generate real mouse events on the host without any confirmation, dry-run mode, bounds validation, or focused-window verification. In a UI automation skill, that means a caller can trigger unintended clicks on sensitive dialogs, permission prompts, security settings, or destructive UI elements, especially if coordinates are stale or manipulated.

Context-Inappropriate Capability

Low
Confidence
91% confidence
Finding
The manifest and top-level documentation describe this skill as controlling the Mac using cliclick and AppleScript, plus screenshots/window bounds. Line L271 introduces an additional automation capability via Python and pyautogui, which is not declared as part of the skill's stated toolset or purpose-specific implementation details.

Static analysis

No suspicious patterns detected.