T09 · Insecure Skill Coding Practices
- Location
scripts/calendar_sync.py:36- Finding
AppleScript Injection Through Unescaped Calendar and LMS Data
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Canvas course helper is purpose-aligned, but it needs Review because unsafe handling of Canvas data could expose the API token, overwrite local files, or run AppleScript locally.
Review before installing. Use a limited-scope Canvas token if possible, avoid committing config.json, run the skill in a dedicated environment, and be cautious with calendar sync and bulk downloads until URL validation, filename containment, AppleScript escaping, and confirmation/preview controls are fixed.
scripts/calendar_sync.py:36AppleScript Injection Through Unescaped Calendar and LMS Data
scripts/canvas_api.py:48Canvas Bearer Token Disclosure Through Unvalidated Response URLs
scripts/canvas_api.py:82Arbitrary File Overwrite Through Canvas Filename Path Traversal
SKILL.md:44Unpinned Third-Party Dependency Installation
The documented behavior materially exceeds or diverges from what is safely declared: it reads local configuration containing a Canvas token, interacts with remote Canvas endpoints, downloads files, and can submit assignments, yet these sensitive behaviors are not transparently bounded in the skill contract. This mismatch can mislead users and orchestrators about the real trust requirements, increasing the chance of unintended data access, remote actions, or credential exposure.
The documented behavior materially exceeds or diverges from what is safely declared: it reads local configuration containing a Canvas token, interacts with remote Canvas endpoints, downloads files, and can submit assignments, yet these sensitive behaviors are not transparently bounded in the skill contract. This mismatch can mislead users and orchestrators about the real trust requirements, increasing the chance of unintended data access, remote actions, or credential exposure.
The README promotes Apple Calendar synchronization as a feature but does not clearly warn users that running the sync will create or modify calendar entries on their local/iCloud-backed calendar. In an agent-skill context, actions that change external state should be explicitly disclosed because users may trigger them through natural-language requests without realizing the side effect.
The README instructs users to place a Canvas API token directly into config.json but does not warn that this token is a sensitive credential that grants API access to coursework, grades, submissions, and other account data. Storing secrets in a plaintext file inside a cloned skill directory increases the risk of accidental disclosure through backups, file sharing, screenshots, or source control mistakes.
The skill documentation describes capabilities that require shell execution, network access, and local file read/write, but it does not declare any tool scope or permission boundaries. In an agent environment, this omission can cause over-privileged or ambiguous execution, making it easier for the skill to access tokens, user files, download remote content, or submit assignments without explicit policy gating.
The trigger keywords include very broad academic terms like '课程', '作业', '成绩', 'PPT', '总结', 'course', and 'assignment', which are likely to appear in many normal conversations. Over-broad triggers can invoke a high-privilege skill unexpectedly, exposing local files, tokens, or causing remote actions such as downloads or assignment submission in contexts where the user did not intend to use this skill.
The code forces Asia/Shanghai time via TZ_SHANGHAI and presents user-visible messages/calendar names only in Chinese, with no opt-in or configuration for language/locale behavior. Under the policy, forcing a specific language or locale without user choice is a natural-language policy violation unless clearly justified as region-specific.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
end if
end tell
'''
r = subprocess.run(["osascript", "-e", script], capture_output=True, text=True, timeout=30)
return r.returncode == 0
def create_event(summary, due_dt, description=""):
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
end if
end tell
'''
r = subprocess.run(["osascript", "-e", script], capture_output=True, text=True, timeout=30)
return r.returncode == 0
def create_event(summary, due_dt, description=""):
The code constructs AppleScript by directly interpolating untrusted summary and description values into a quoted script string, then executes it via osascript. If course or assignment data from Canvas contains quotes or AppleScript syntax, an attacker-controlled course item could break out of the string literal and inject unintended AppleScript actions on the local machine.
end tell
end tell
'''
r = subprocess.run(["osascript", "-e", script], capture_output=True, text=True, timeout=30)
return r.returncode == 0
def list_existing_events():
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def sync_ddls(ddls):
"""同步 DDL 列表到 Apple Calendar(跳过已存在的)"""
# 启动日历
subprocess.run(["open", "-a", "Calendar"], capture_output=True)
import time; time.sleep(2)
ensure_calendar()
The script modifies a user's Apple Calendar by creating events automatically, with no confirmation, dry run, or preview of what will be added. In this skill context, data originates from external course content, so malformed or malicious assignment names could lead to unwanted calendar changes at scale and reduce trust in the agent.
The docstring says the function uploads files and submits an assignment, but the code builds request URLs using expressions like get_base_url()/api/v1/..., which is invalid Python/string construction and will not perform the documented Canvas API calls. This is an active divergence between the documented intent and the implemented behavior.
This code performs a state-changing action: it uploads local files and submits an assignment using the user's bearer token, but contains no built-in confirmation, dry-run mode, or guardrails in the submission function itself. In an agent setting, that makes accidental or unauthorized submission easier if higher-level orchestration invokes it based on ambiguous prompts, potentially sending the wrong files or submitting before the user intends.
The file's primary description string is in Chinese, and the script also uses Chinese-only user-facing messages elsewhere, indicating the skill is designed around a fixed language. This can violate language/locale policy because it does not offer user opt-in or document that the tool is intentionally region-specific.
Returned strings such as installation guidance, unsupported-file errors, and extraction-failure messages are presented only in Chinese. Because these are user-visible outputs in a code file, they enforce a locale choice without giving the user an alternative or explaining a justified regional restriction.
The config uses Chinese-only default values for save_dir and calendar_name (Canvas课件, Canvas作业). This can impose a specific language/locale on users without opt-in, which matches the natural-language policy violation criteria for forced language settings.
The module docstring and multiple user-facing strings are written only in Chinese, which indicates a fixed language choice in the skill's natural-language interface. There is no visible opt-in, language selection, or documentation in this file that the skill is intentionally restricted to a Chinese-speaking audience.
The manifest describes the skill as managing Canvas course data and mentions syncing DDLs to Apple Calendar, but this module directly exposes Canvas calendar event listing as a first-class API operation. That capability is adjacent to the stated purpose, yet it is broader than the module's own documented scope of courses/files/assignments/grades/discussions and not clearly required for the claimed core Canvas data management behavior.
No suspicious patterns detected.