Back to skill

Security audit

court-notice

Security checks for vulnerabilities and agentic risk

Overview

This skill automates sensitive court-document handling but uses silent downloads, Calendar writes, and persistent reminders without enough validation or user control.

Review carefully before installing. Only use this with trusted court-document sources and after adding explicit confirmation before downloads, Calendar writes, and reminders. The helper should validate URLs, avoid fixed Desktop overwrites, stop printing full document text by default, replace LaunchAgents with Calendar-native alerts where possible, and escape or pass all AppleScript/plist values as data rather than executable source.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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)

T06 · System Persistence

Warning
Location
scripts/create_court_calendar.py:75
Finding

Persistent LaunchAgent Is Installed Without Automatic Cleanup

Content
View full analysis
Label com.mm.court-{uid_hash} ProgramArguments /usr/bin/osascript -e display notification "{notification_text}" with title "Court Hearing Reminder" StartCalendarInterval Hour {start_dt.hour} Minute {start_dt.minute} Month {alarm_dt.month} Day {alarm_dt.day} ''' os.makedirs(os.path.dirname(plist_path), exist_ok=True) with open(plist_path, 'w') as f: f.write(plist_content) subprocess.run(['launchctl', 'load', plist_path], capture_output=True) ``` ### Technical Analysis The script writes a property-list file to the user's `~/Library/LaunchAgents` directory and immediately loads it with `launchctl`. A LaunchAgent is a cross-session persistence mechanism that can run after the original skill invocation has ended. The persistence is related to the advertised reminder functionality, but its lifecycle is unsafe ...[truncated 1619 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create_court_calendar.py:44
Finding

Untrusted Document and Command-Line Fields Are Interpolated into AppleScript Source

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create_court_calendar.py:77
Finding

Untrusted Fields Are Embedded in a LaunchAgent Plist Without XML or AppleScript Escaping

Content
View full analysis
Label com.mm.court-{uid_hash} ProgramArguments /usr/bin/osascript -e display notification "{notification_text}" with title "Court Hearing Reminder" StartCalendarInterval Hour {start_dt.hour} Minute {start_dt.minute} Month {alarm_dt.month} Day {alarm_dt.day} ''' os.makedirs(os.path.dirname(plist_path), exist_ok=True) with open(plist_path, 'w') as f: f.write(plist_content) subprocess.run(['launchctl', 'load', plist_path], capture_output=True) ``` ### Technical Analysis The notification text includes `case_type`, `case_no`, and `location`, which can contain text extracted from an untrusted PDF. That text is inserted into two nested executable formats: 1. An XML property-list `` element. 2. An AppleScript expression stored inside that element. No XML escaping or AppleScript escaping is performed. Characters such as `&`, `<`, and `>` can change or invalidate the XML structure. Quotation marks and AppleScript syntax can terminate the notification string and add executable statements. The generated plist is ...[truncated 1785 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:66
Finding

SMS-Controlled URLs Are Downloaded Without Scheme, Destination, or Content Validation

Content
View full analysis
" ``` The documented SMS format identifies the URL as an externally supplied field: ```text [COURT NAME] The court has sent documents relating to case {case number}. Please review them at: {link} ``` The reference example also permits a plaintext HTTP URL targeting a private-network address. ### Technical Analysis The skill directs the agent to download a URL obtained from a court-themed SMS. It does not require: - HTTPS. - An approved court domain. - Publicly routable destinations. - DNS and redirect revalidation. - A PDF content type or valid PDF signature. - A maximum response size. - A unique destination filename. - User confirmation before network access. This creates a server-side request forgery-style capability from the perspective of the agent environment. A malicious SMS can direct the downloader to loopback, private, link-local, or otherwise sensitive network endpoints reachable from the user's machine. The use of a fixed Desktop path also overwrites an existing file with the same name. In environments where another local process can manipulate that path, symlink or replacement-file behavior may increase the overwrite risk. This finding concerns unrestricted data retrieval, not remote payload execution: the documented command downloads the response and the reviewed code does not directly execute the downloaded PDF as native code. ### Attack Path 1. An attacker sends or forwards a message that resembles the documented court SMS template. 2. The message contains an attacker-selected URL. 3. The skill follows the workflow and invokes `curl` without validating the destination. 4. The user's machine requests the selected public or internal endpoint. 5. Redirects or DNS resolution may lead ...[truncated 1075 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (35)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This mismatch indicates the skill advertises automatic SMS/PDF handling while apparently relying on manual CLI inputs and exposing additional behavior like console output of document contents. Such discrepancies can conceal privacy-sensitive processing and break assumptions about when and how the skill activates.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

This mismatch indicates the skill advertises automatic SMS/PDF handling while apparently relying on manual CLI inputs and exposing additional behavior like console output of document contents. Such discrepancies can conceal privacy-sensitive processing and break assumptions about when and how the skill activates.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger language is broad enough to activate on any received or forwarded court SMS or any request to process a court PDF, which risks autonomous execution on loosely matched content. In this context, broad activation is especially risky because the workflow performs downloads, calendar writes, and reminder setup without a clear human approval checkpoint.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill explicitly promises silent, zero-popup automatic downloads, calendar modifications, reminder creation, and Desktop file writes. Silent side effects on user data and system state are dangerous because they remove informed consent and make malicious or mistaken actions harder for the user to detect and stop.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The workflow step sequence includes direct calendar writes and launchd-based reminder setup with no user warning. That combination changes both application data and system behavior, and can be abused to create stealthy persistence-like scheduled actions or unwanted notifications from untrusted input.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares no explicit tool scope while instructing shell execution and file writes, including downloading a PDF to the Desktop and creating persistence-related plist files. Missing permission boundaries increases the chance that an agent can perform filesystem and command actions without clear user-approved limits.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The skill description, workflow, templates, and outputs are written entirely in Chinese and assume Chinese-language court notices, but no user opt-in or locale limitation is explicitly documented as a policy choice. This can constitute a language/locale constraint imposed without presenting the user with a choice.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

Using a launchd plist to schedule reminders introduces persistence beyond the immediate session. Persistence mechanisms are security-sensitive because they can outlive the user's awareness, repeatedly execute actions, and be repurposed if inputs or file contents are manipulated.

Content

Scanner excerpt · SKILL.md (reported line 17)May include surrounding context.

  1. pypdf提取文本内容
  2. 判断文书类型(传票/出庭通知→建日历,其他→仅汇报)
  3. AppleScript直接写入"工作"日历(无弹窗)
  4. launchd plist设置提前1天系统通知提醒
  5. 生成文书概要报告
  6. PDF存桌面回传用户
text

Session Persistence

Medium
Category
Rogue Agent
Confidence
92% confidence
Finding

The explicit instruction to write a plist under ~/Library/LaunchAgents creates user-level persistence on macOS. Even if intended only for reminders, persistence in a skill handling externally supplied links and documents raises the risk of stealthy recurring behavior and complicates user control and auditing.

Content

Scanner excerpt · SKILL.md (reported line 54)May include surrounding context.

时间格式:YYYY-MM-DD HH:MM(如 2026-04-24 10:00)

launchd plist存至 ~/Library/LaunchAgents/com.mm.court-{案号hash}.plist

3. 下载PDF到桌面

bash

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Downloading a linked PDF directly to the user's Desktop from message content, without warning, creates privacy and integrity risks. The Desktop is highly visible and commonly synced/backed up, so sensitive court documents could be exposed, and untrusted links could deliver unexpected or malicious content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The document is entirely written in Chinese and defines processing rules, keywords, and outputs only for Chinese-language legal document types. There is no indication that the skill is region-specific, justified by a documented locale requirement, or offers users any language or locale choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file is entirely framed as a fixed Chinese SMS template for court notifications, and the example/recommended formats provide no option for alternative languages or user locale selection. Under the policy criteria, forcing a specific language without opt-in or documented regional justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The code explicitly documents use of a launchd plist for future execution, indicating persistence in the user session. Persistence is security-relevant in this skill context because the advertised task is court-calendar automation, yet the implementation adds a host-resident mechanism that survives beyond the immediate action.

Content

Scanner excerpt · scripts/create_court_calendar.py (reported line 24)May include surrounding context.

python
- description: 案号 - 案由 - 开庭地点(不含链接,纯文本)
       - url: PDF链接(如有)
       - location: 开庭地点
    2. launchd plist设置提前1天提醒(系统通知中心)
    """

    from datetime import datetime, timedelta

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/create_court_calendar.py (reported line 59)May include surrounding context.

python
f.write(script)
    f.close()

    result = subprocess.run(['osascript', f.name], capture_output=True, text=True)
    subprocess.run(['rm', '-f', f.name])

    if result.returncode != 0:

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/create_court_calendar.py (reported line 120)May include surrounding context.

python
f.write(script)
    f.close()

    result = subprocess.run(['osascript', f.name], capture_output=True, text=True)
    subprocess.run(['rm', '-f', f.name])

    if result.returncode != 0:

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/create_court_calendar.py (reported line 60)May include surrounding context.

python
f.close()

    result = subprocess.run(['osascript', f.name], capture_output=True, text=True)
    subprocess.run(['rm', '-f', f.name])

    if result.returncode != 0:
        print(f"AppleScript error: {result.stderr}")

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/create_court_calendar.py (reported line 121)May include surrounding context.

python
f.close()

    result = subprocess.run(['osascript', f.name], capture_output=True, text=True)
    subprocess.run(['rm', '-f', f.name])

    if result.returncode != 0:
        print(f"AppleScript error: {result.stderr}")

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

This section begins creation of a LaunchAgent plist under ~/Library/LaunchAgents, a standard persistence location on macOS. Such persistence is broader than needed for creating a court calendar entry and may leave behind scheduled behavior the user does not expect.

Content

Scanner excerpt · scripts/create_court_calendar.py (reported line 66)May include surrounding context.

python
print(f"AppleScript error: {result.stderr}")
        return False

    # 创建launchd plist(提前1天提醒)
    uid_hash = hashlib.md5(case_no.encode()).hexdigest()[:8]
    plist_path = os.path.expanduser(f"~/Library/LaunchAgents/com.mm.court-{uid_hash}.plist")

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script installs a persistent launchd agent for reminders, which broadens capability from simple calendar creation into persistence on the host. In a skill intended to process court notices automatically, that hidden system-level persistence is more dangerous because users would reasonably expect a calendar event or reminder, not a resident LaunchAgent.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
97% confidence
Finding

The code computes a plist path in the user LaunchAgents directory, indicating intent to establish session persistence. In an auto-processing legal-document skill, hidden persistence increases risk because it creates lasting system modifications outside the narrow user request.

Content

Scanner excerpt · scripts/create_court_calendar.py (reported line 68)May include surrounding context.

python
# 创建launchd plist(提前1天提醒)
    uid_hash = hashlib.md5(case_no.encode()).hexdigest()[:8]
    plist_path = os.path.expanduser(f"~/Library/LaunchAgents/com.mm.court-{uid_hash}.plist")

    notification_text = f"⚖️ 明日上午{start_dt.strftime('%H点%M分')}开庭:{case_type}\\n案号:{case_no}\\n地点:{location}"

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

Construction of the plist content is part of implementing persistent scheduled execution. This is security-significant because it creates a reusable mechanism for future code execution/notifications beyond the immediate document-processing operation.

Content

Scanner excerpt · scripts/create_court_calendar.py (reported line 72)May include surrounding context.

python
notification_text = f"⚖️ 明日上午{start_dt.strftime('%H点%M分')}开庭:{case_type}\\n案号:{case_no}\\n地点:{location}"

    plist_content = f'''<?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>

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The PLIST structure creation is another indicator of LaunchAgent persistence. In this skill context, persistent scheduled actions are more sensitive because the feature is framed as routine automation rather than host modification.

Content

Scanner excerpt · scripts/create_court_calendar.py (reported line 73)May include surrounding context.

python
notification_text = f"⚖️ 明日上午{start_dt.strftime('%H点%M分')}开庭:{case_type}\\n案号:{case_no}\\n地点:{location}"

    plist_content = f'''<?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>

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The PLIST structure creation is another indicator of LaunchAgent persistence. In this skill context, persistent scheduled actions are more sensitive because the feature is framed as routine automation rather than host modification.

Content

Scanner excerpt · scripts/create_court_calendar.py (reported line 73)May include surrounding context.

python
notification_text = f"⚖️ 明日上午{start_dt.strftime('%H点%M分')}开庭:{case_type}\\n案号:{case_no}\\n地点:{location}"

    plist_content = f'''<?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>

Session Persistence

Medium
Category
Rogue Agent
Confidence
92% confidence
Finding

The Label entry forms part of a registered LaunchAgent, which enables the job to be loaded and tracked by launchd. That persistence is unnecessary for simple reminder behavior and creates a broader, more durable foothold in the user session than expected.

Content

Scanner excerpt · scripts/create_court_calendar.py (reported line 74)May include surrounding context.

python
plist_content = f'''<?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>
    <string>com.mm.court-{uid_hash}</string>

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

This point closes out the generated plist, confirming a complete persistence artifact is being assembled. The risk is not the XML syntax itself but the fact that a host-level scheduled job is being created for a task that should not require it.

Content

Scanner excerpt · scripts/create_court_calendar.py (reported line 96)May include surrounding context.

python
<integer>{alarm_dt.day}</integer>
    </dict>
</dict>
</plist>'''

    os.makedirs(os.path.dirname(plist_path), exist_ok=True)
    with open(plist_path, 'w') as f:

Static analysis

No suspicious patterns detected.