Back to skill

Security audit

Notesctl

Security checks for vulnerabilities and agentic risk

Overview

This Apple Notes helper is mostly purpose-aligned, but it needs review because a crafted folder name can turn note creation into local command execution.

Review before installing. Use only with trusted note titles, bodies, and especially folder names, and prefer installing after the folder handling is fixed by passing values to osascript as arguments or strictly validating folder names. Expect the skill to create, list, search, and export Apple Notes using your macOS user permissions.

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 (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/notes_new.sh:10
Finding

AppleScript Injection Through an Unescaped Folder Name

Content
View full analysis
&2 exit 1 fi # Notes body is HTML-ish: escape + convert newlines to
export TITLE BODY BODY_HTML=$(python3 - <<'PY' import html, os s = os.environ.get('BODY','') print(html.escape(s).replace('\n','
')) PY ) # Escape for AppleScript string literal export BODY_HTML BODY_AS=$(python3 - <<'PY' import os s=os.environ['BODY_HTML'] print(s.replace('\\','\\\\').replace('"','\\"')) PY ) TITLE_AS=$(python3 - <<'PY' import os s=os.environ['TITLE'] print(s.replace('\\','\\\\').replace('"','\\"')) PY ) osascript -e "tell application \"Notes\" to make new note at folder \"$FOLDER\" with properties {name:\"$TITLE_AS\", body:\"$BODY_AS\"}" ``` The vulnerable argument can also originate from JSON input: ```bash FOLDER=$(python3 - <<'PY' import json, os obj=json.loads(os.environ.get('NOTES_PAYLOAD','') or '{}') print(obj.get('folder','Notes')) PY ) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" "$SCRIPT_DIR/notes_new.sh" "$TITLE" "$BODY" "$FOLDER" >/dev/null ``` ### Technical Analysis The script dynamically constructs AppleScript source inside a shell string. Although the title and body undergo limited escaping for AppleScript string literals, `FOLDER` is interpolated directly into the source without escaping or validation: ```bash folder \"$FOLDER\" ``` Shell quoting prevents the folder value from becoming a separate shell command, but it does not prevent the value from altering the AppleScript program passed to `osascript`. An attacker-controlled folder name can contain quotation marks, AppleScript statement separators or line breaks, additional statements, and ...[truncated 2193 chars]
Remediation
View remediation
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (2)

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest describes notesctl as able to 'create, append, list, search, export, and edit' Apple Notes, but this file's inventory of shipped scripts does not include append or edit functionality. The README further says editing existing notes is intentionally not the default workflow and points users to an external memo notes -e command instead, which suggests the advertised capabilities are not actually implemented by the skill itself.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill invokes local scripts and relies on host binaries (memo, python3, osascript) but does not declare an explicit tool/permission scope. That creates an authorization gap: an agent or runtime may permit broader environment or execution access than intended, making it harder to constrain what the skill can touch or spawn if the bundled scripts are modified or behave unexpectedly.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.