T09 · Insecure Skill Coding Practices
- Location
reminders/apple-bridge.js:141- Finding
AppleScript Injection Through Reminder Title or Note
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill mostly does what it says, but one add-reminder path builds executable AppleScript from reminder text in a way that could let crafted titles or notes run unintended local commands.
Install only if you are comfortable granting a local skill access to your macOS Reminders data. Avoid adding reminders from untrusted copied text until the AppleScript construction path is fixed or all adds use EventKit. Review delete/complete requests carefully because they modify live reminder data and may sync across Apple devices.
reminders/apple-bridge.js:141AppleScript Injection Through Reminder Title or Note
The code substantially matches the core Reminders integration claims: it interacts with macOS Reminders, supports listing calendars/reminders, adding reminders, recurrence via a Swift helper, priority, list selection, query search, and edit/delete/complete by ID. However, the declared description includes capabilities not present in the supplied code chunk: there is no 'parse' command and no text-only meeting-notes parsing logic, and there is no multilingual trigger detection or response-formatting logic for en/ko/ja/zh. These are material declared features absent from the actual implementation, so this is a description-behavior mismatch.
Referenced artifact was not completely inspected
- `reminders/meeting-parser.js` (meeting notes parser for action item extraction)
Referenced artifact was not completely inspected
- `locales.json` (language-specific triggers and responses)
Referenced artifact was not completely inspected
- `locales.json` (language-specific triggers and responses)
Referenced artifact was not completely inspected
- `locales.json` (language-specific triggers and responses)
The README documents delete and complete operations, and the same document emphasizes that reminder changes sync automatically across all Apple devices via iCloud. Without an explicit warning or confirmation guidance, users may trigger destructive or state-changing actions that propagate account-wide, causing unintended data loss or incorrect task completion.
The README states a default timezone of +09:00 (KST) and suggests hard-coding parsing logic to that offset. In a scheduling skill, this can silently create reminders at the wrong time for users in other regions, leading to missed deadlines or reminders firing at unexpected hours.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
# Edit crontab
crontab -e
# Morning reminder check (9 AM daily)
0 9 * * * cd ~/clawd && node skills/mac-reminders-agent/cli.js list --scope today --locale ko >> /tmp/reminders.log 2>&1
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Create ~/Library/LaunchAgents/com.reminders.daily.plist:
<?xml version="1.0" encoding="UTF-8"?>
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Create ~/Library/LaunchAgents/com.reminders.daily.plist:
<?xml version="1.0" encoding="UTF-8"?>
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Create ~/Library/LaunchAgents/com.reminders.daily.plist:
<?xml version="1.0" encoding="UTF-8"?>
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Create ~/Library/LaunchAgents/com.reminders.daily.plist:
<?xml version="1.0" encoding="UTF-8"?>
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Create ~/Library/LaunchAgents/com.reminders.daily.plist:
<?xml version="1.0" encoding="UTF-8"?>
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Load with:
launchctl load ~/Library/LaunchAgents/com.reminders.daily.plist
Broad natural-language triggers like everyday scheduling phrases can cause accidental invocation of a skill that has write/delete capabilities over local reminders. In an agent environment, ambiguous routing can lead to unintended reads or modifications of user task data without sufficiently explicit intent.
The documentation permits destructive deletion by ID without specifying an explicit confirmation step or warning. In an LLM-agent setting, this increases the risk of irreversible user-data loss from misinterpretation, prompt ambiguity, stale IDs, or accidental tool invocation.
The manifest says the skill can add and edit reminders, supports native recurrence via EventKit, and uses titles for search, but it does not disclose that the CLI rewrites every added reminder title by appending human-readable recurrence labels and due timestamps. This changes reminder content beyond the user's supplied title and can affect later search, display, and edit behavior, making the actual behavior broader than the described reminder-management interface.
The delete command directly invokes the reminder bridge to remove a reminder by ID, but this file provides no confirmation prompt or explicit warning before performing the irreversible action. Although a success message is printed afterward, that is not a user disclosure before the destructive operation occurs.
This JSON manifest defines activation trigger phrases, so SQP-1 applies. Phrases like "今日のタスクは?", "今週の予定は?", and similar equivalents in other locales are broad everyday utterances and do not clearly constrain invocation to reminders rather than general planning, calendar, or to-do contexts.
Examples like "有哪些列表?", "リストは何がある?", and similar list-oriented prompts are context-poor and could match many unrelated list-discovery actions outside reminders. Because the manifest provides only examples and no exclusion conditions, these broad phrases risk unintended activation.
The deleteReminder function performs a destructive delete operation through the Swift helper with no confirmation prompt, warning message, or user disclosure in the code path. Because deletion can irreversibly remove user reminder data, this safety-critical action should be explicitly disclosed before execution.
The delete command removes a reminder immediately once an ID is supplied, with no secondary confirmation, dry-run mode, or trust boundary check. In an agent context where IDs may be selected from prior tool output or inferred from user conversation, a mistaken, spoofed, or prompt-manipulated action can irreversibly delete user data.
The code infers the input language from character ranges and falls back to 'en' when no CJK/Korean script is detected. This imposes a language/locale decision automatically, which can mis-handle multilingual or ambiguous text without explicit user choice.
Lines L076-L081 state that natural language requests are handled in only two cases: list and add. This directly conflicts with the same file's documented support for lists, edit, delete, complete, recurrence, and parse operations, creating an intent/documentation mismatch about the skill's actual supported behavior.
Detected: suspicious.dangerous_exec