Back to skill

Security audit

MacOS Desktop Control

Security checks for vulnerabilities and agentic risk

Overview

This macOS desktop-control skill is mostly coherent, but it needs review because it combines screen, mouse, keyboard, clipboard, and AppleScript authority with real implementation flaws that can expose pasted text or allow AppleScript injection.

Review before installing. Use this only in a dedicated, low-sensitivity macOS session, avoid pasting secrets through it, clear or protect generated screenshots, and do not pass untrusted app names until the AppleScript interpolation and pasted-text logging issues are fixed.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/applescript_app.py:42
Finding

AppleScript Injection Through Unescaped Application Names

Content
View full analysis
0 then', 'return name of front window', 'else', 'return ""', 'end if', 'end tell', 'end tell', ]) ``` ### Technical Analysis The `--app` command-line value is inserted directly into Appl ...[truncated 1880 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/calibration.py:7
Finding

Symlink-Unsafe Writes to a Predictable Shared Temporary Directory

Content
View full analysis
None: DEFAULT_STATE_DIR.mkdir(parents=True, exist_ok=True) def save_calibration(data: Dict[str, Any], path: Path = DEFAULT_CALIBRATION_PATH) -> None: ensure_state_dir() path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding='utf-8') ``` The default path is also exposed through the initialization command: ```python parser.add_argument('--output', type=Path, default=DEFAULT_CALIBRATION_PATH) args = parser.parse_args() data = detect_mapping() save_calibration(data, args.output) ``` ### Technical Analysis Calibration state is stored under the globally predictable path `/tmp/macos_desktop_control/calibration.json`. The directory is created with `exist_ok=True`, but the code does not verify that an existing directory is owned by the current user, has restrictive permissions, or is not otherwise attacker-controlled. `Path.write_text()` follows symbolic links and truncates the destination. No no-follow, exclusive-creation, ownership, regular-file, or atomic-replacement checks are performed. Consequently, another local user or process that can prepare the temporary path may redirect the calibration write to another file that the victim account is permitted to modify. The calibration loader also trusts an existing file without validating its ownership or structure, allowing attacker-controlled values to influence coordinate conversion and desktop actions. ### Attack Path 1. Before the victim uses the skill, a local attacker prepares the predictable `/tmp/macos_desktop_control` path under conditions that permit the victim process to access it. 2. The attacker places ...[truncated 947 chars]
Remediation
View remediation
` or `~/Library/Caches/` rather than a shared `/tmp` pathname. - Create the state directory with mode `0700` and verify that it is owned by the current effective user. - Reject symbolic links and non-regular files for both the directory and calibration file. - Open new files using no-follow and exclusive-creation semantics where supported. - Write to a securely created temporary file in the same trusted directory, flush and synchronize it, and atomically replace the destination. - Set calibration files to mode `0600`. - Validate loaded JSON fields, numeric ranges, dimensions, and scale factors before using them. - If temporary storage remains necessary, create a per-user directory using a securely generated name rather than a fixed global path. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/keyboard.py:44
Finding

Sensitive Pasted Text Is Disclosed Through Standard Output

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned and Unhashed Third-Party Dependencies

Content
View full analysis
=0.9.54 Pillow>=10.0.0 opencv-python>=4.8.0 pyobjc-framework-Vision>=10.0 pyobjc-framework-Quartz>=10.0 ``` The documented installation command is: ```bash pip install -r requirements.txt ``` ### Technical Analysis Every dependency uses an open-ended minimum-version constraint. A new installation may therefore retrieve any future release accepted by the resolver rather than a specifically reviewed version. No lock file or package hashes are provided to verify artifact integrity. The reviewed package names do not, by themselves, establish dependency confusion or typosquatting. The confirmed weakness is that the effective installed code can change over time without a corresponding change to this project, reducing reproducibility and increasing exposure to compromised upstream releases, malicious distribution artifacts, or incompatible updates. Python package installation can execute build-backend or installation-related code, so dependency integrity is especially important for a desktop-control skill with Screen Recording and Accessibility permissions. ### Attack Path 1. A user follows the documented `pip install -r requirements.txt` command. 2. The package resolver queries the configured Python package index. 3. It selects the newest available versions satisfying the open-ended lower bounds. 4. Those versions may differ from the releases originally tested or reviewed. 5. If an upstream account, release, package index, or build artifact is compromised, malicious package code can execute during installation or when imported by the skill. 6. That code runs with the privileges of the installing or executing user. ### Impact Assessment A compromised dependency could execute arbitrary cod ...[truncated 349 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description claims a broad generic macOS desktop control tool including app and window semantics as well as screenshot, OCR, mouse, and keyboard workflows. The supplied code only implements four app-level actions: open an app or app bundle path, activate/make an app frontmost, test whether an app is running, and query the frontmost app. It does not implement screenshots, OCR, mouse input, keyboard input, or meaningful window control. This is therefore a description-behavior mismatch due to substantial overstatement of capabilities, even though the AppleScript/macOS app-control portion is partially accurate.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description presents a broad macOS desktop control skill with multiple interaction modalities (AppleScript app/window semantics, screenshots, OCR, mouse, keyboard workflows). The supplied code only implements read-only window inspection for a named application process: retrieving the front window title, window count, or all window titles. It does not perform screenshots, OCR, mouse input, keyboard input, or broader desktop control actions. While the AppleScript/window-semantics portion is related, the actual code is materially narrower than the declared purpose, so the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description describes a broad macOS desktop automation skill involving AppleScript, screenshots, OCR, and input control. The supplied code only implements image cropping on an existing image file using PIL. This is a materially different primary purpose and lacks the core declared behaviors entirely. Therefore the description does not accurately represent the code chunk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill documents shell execution, file reads/writes, screenshot capture, and desktop automation, but it does not declare any explicit tool scope such as allowed-tools or permissions. That omission weakens containment and review because an agent may invoke broad local capabilities without a clear least-privilege contract, which is especially risky for a desktop-control skill with access to screen contents and input synthesis.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill description and feature list present AI semantic understanding as a core built-in visual targeting method, yet the documented scripts list includes locate_text_ocr.py and locate_image_opencv.py without any corresponding AI semantic locator implementation. This overstates what the skill itself appears to actually provide, making the claimed behavior broader than the documented code surface.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill encourages screenshot capture and OCR over arbitrary desktop content but does not explicitly warn that these operations may collect passwords, messages, tokens, financial data, or other sensitive on-screen information. In a desktop-control context, that omission is meaningful because operators may use the skill in privileged sessions and underestimate the privacy and exfiltration risk of captured images and OCR output.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The heading and surrounding text say AI semantic understanding is the default first-choice locator, but the example command under that heading invokes locate_text_ocr.py with a text string. This actively contradicts the documented distinction between AI semantic understanding and OCR fallback.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill defaults to clipboard-based paste for all text input but does not clearly warn that this can overwrite the user's clipboard and may paste secrets into the wrong field if focus is incorrect. In a desktop automation skill that can click and paste into arbitrary apps, this can cause unintended disclosure of sensitive text or destructive actions in the wrong context.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
97% confidence
Finding

The code builds AppleScript source by directly interpolating the untrusted --app argument into script lines passed to osascript. An attacker can inject quotes and additional AppleScript statements, leading to arbitrary AppleScript execution, which in this macOS desktop-control context can drive apps, read UI state, trigger clicks/keystrokes, and potentially access sensitive user data via automation permissions.

Content

Scanner excerpt · scripts/applescript_app.py (reported line 12)May include surrounding context.

python
def run_osascript(lines: List[str]) -> str:
    proc = subprocess.run(
        ["osascript", *sum([["-e", line] for line in lines], [])],
        check=True,
        capture_output=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/applescript_app.py (reported line 44)May include surrounding context.

python
if args.action == 'open':
        if args.path:
            subprocess.run(['open', args.path], check=True)
            emit(build_result('open', path=args.path, launch='open-path'), args.json_pretty)
            return
        if not args.app:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

The code builds AppleScript source using an f-string with untrusted input (args.app) and passes it directly to osascript. Although subprocess.run is invoked without a shell, this is still an AppleScript injection issue: a crafted application name containing quotes and script fragments can break out of the string literal and execute arbitrary AppleScript commands, enabling UI automation, data access, or other desktop actions under the user's permissions.

Content

Scanner excerpt · scripts/applescript_window.py (reported line 12)May include surrounding context.

python
def run_osascript(lines: List[str]) -> str:
    proc = subprocess.run(
        ["osascript", *sum([["-e", line] for line in lines], [])],
        check=True,
        capture_output=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script captures the entire macOS screen and writes it to a predictable file path under /tmp without any built-in notice, consent prompt, or disclosure mechanism. In a desktop-control skill, screenshots can contain sensitive data such as credentials, messages, or documents, so silent persistence of captured images increases privacy and data-exposure risk even if the feature is intended for automation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script can write arbitrary text to the macOS clipboard and immediately simulate Command+V without any confirmation, warning, or target validation. In a desktop-control skill, this can cause unintended data entry into whatever window has focus, including terminals, password fields, chats, or admin consoles, increasing the risk of secret leakage or destructive command execution.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/keyboard.py (reported line 28)May include surrounding context.

python
def copy_to_clipboard(text: str) -> None:
    subprocess.run(['pbcopy'], input=text, text=True, check=True)


def main() -> None:

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The introductory text is in Chinese and explicitly reassures Chinese users, which creates a locale-specific framing without any corresponding statement that other languages/locales are equally supported or user-selectable. Under the policy, language or locale constraints should be optional, documented as justified, or offer user choice.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The feature list states the skill can "Type text" as part of keyboard control, while later guidance says text entry should not use simulated typing and instead always use clipboard paste. Those statements describe different intended behaviors for how text input is performed.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is specified with a lower bound only, which allows future unreviewed versions to be installed and makes builds non-reproducible. In a desktop-control skill with GUI automation privileges, a compromised or breaking upstream release could introduce supply-chain risk or unsafe behavior.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
pyautogui>=0.9.54
Pillow>=10.0.0
opencv-python>=4.8.0
pyobjc-framework-Vision>=10.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

Pillow is unpinned and has a history of security advisories, so using only a minimum version leaves the installed version uncertain and non-reproducible. Because this skill processes screenshots/images, image-parsing dependencies are directly in the execution path, increasing exposure if a vulnerable release is resolved.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
pyautogui>=0.9.54
Pillow>=10.0.0
opencv-python>=4.8.0
pyobjc-framework-Vision>=10.0
pyobjc-framework-Quartz>=10.0

Unverifiable Dependency: Pillow has 16 known advisory(ies) (CVE-2016-2533 (Pillow buffer overflow in ImagingPcdDecode); CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2021-27922 (Pillow Uncontrolled Resource Consumption) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
97% confidence
Finding

Pillow has multiple known advisories, and because the requirement is not pinned, there is no assurance that installs will avoid affected versions. This is especially relevant here because the skill handles screenshots and OCR inputs, so vulnerable image-processing code would likely be exercised.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

opencv-python is unpinned, so dependency resolution may select different versions over time, including releases with known flaws or regressions. Since the skill uses OCR/computer-vision workflows, OpenCV is a core attack surface and this context makes version uncertainty more relevant than in a package that never handles images.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
pyautogui>=0.9.54
Pillow>=10.0.0
opencv-python>=4.8.0
pyobjc-framework-Vision>=10.0
pyobjc-framework-Quartz>=10.0

Unverifiable Dependency: opencv-python has 16 known advisory(ies) (CVE-2017-12864 (Integer Overflow or Wraparound in OpenCV); CVE-2017-12598 (Out-of-bounds Read in OpenCV ); CVE-2019-14493 (NULL Pointer Dereference in OpenCV.) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
97% confidence
Finding

opencv-python has known security advisories, and the unpinned requirement means a vulnerable version could be installed without visibility. Because OpenCV is central to this skill’s screenshot/OCR and vision pipeline, any parser or memory-safety issue in the library is more likely to be reachable.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The Vision framework binding is not pinned to an exact version, which weakens reproducibility and allows unreviewed upstream changes into builds. While this is usually lower risk than native parsing libraries with many CVEs, it still creates supply-chain uncertainty in a privileged automation skill.

Content

Scanner excerpt · requirements.txt (reported line 4)May include surrounding context.

text
pyautogui>=0.9.54
Pillow>=10.0.0
opencv-python>=4.8.0
pyobjc-framework-Vision>=10.0
pyobjc-framework-Quartz>=10.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The Quartz framework binding is also specified as a minimum version only, allowing future dependency drift. For a macOS desktop-control skill interacting with display/input APIs, dependency integrity matters because these libraries operate in a sensitive, high-privilege workflow.

Content

Scanner excerpt · requirements.txt (reported line 5)May include surrounding context.

text
Pillow>=10.0.0
opencv-python>=4.8.0
pyobjc-framework-Vision>=10.0
pyobjc-framework-Quartz>=10.0

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code hard-codes recognition languages to Simplified Chinese, Traditional Chinese, and US English. Under the natural-language policy rule, forcing specific languages without user opt-in or a documented region-specific justification is a locale policy concern.

Content

No source excerpt is available for this finding.