Back to skill

Security audit

Chinese Holiday Assistant

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Chinese holiday lookup skill with a small, disclosed updater, though users should be aware that calendar updates fetch and replace local data.

Install only if you want a China-focused holiday/workday checker. If you enable automatic updates, review the configured calendar URLs first and understand that updates will contact those sources and replace the local ICS file; prefer adding size and validation limits before relying on untrusted sources.

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

Warning
Location
scripts/download_ics.py:25
Finding

Unbounded Download and Expansion of Untrusted ICS Calendar Data

Content
View full analysis

Vulnerability Details

File Location: scripts/download_ics.py:25-29, scripts/holiday_checker.py:21-51, and scripts/holiday_checker.py:93
Vulnerability Type: Uncontrolled resource consumption and terminal output manipulation
Risk Level: Medium

Vulnerable Code

scripts/download_ics.py:25-29:

python
response = requests.get(url, timeout=10)
response.raise_for_status()
with open(DATA_PATH, 'wb') as f:
    f.write(response.content)

scripts/holiday_checker.py:21-51:

python
with open(file_path, 'rb') as f:
    try:
        cal = Calendar.from_ical(f.read())
        for component in cal.walk():
            if component.name == "VEVENT":
                summary = str(component.get('summary'))
                dtstart = component.get('dtstart')
                dtend = component.get('dtend')
                
                if not dtstart:
                    continue
                
                # Get the start date
                start_val = dtstart.dt
                if isinstance(start_val, datetime.datetime):
                    start_date = start_val.date()
                else:
                    start_date = start_val
                
                # Get the end date, if present
                if dtend:
                    end_val = dtend.dt
                    if isinstance(end_val, datetime.datetime):
                        end_date = end_val.date()
                    else:
                        end_date = end_val
                else:
                    # Treat an event without an end date as a single-day event
                    end_date = start_date + datetime.timedelta(days=1)
                
                # Add every date covered by the event
                curr = start_date
                while curr < end_date:
                    holiday_map[curr] = summary
                    curr += datetime.timede
...[truncated 3238 chars]
Remediation
View remediation

Remediation Suggestions

  1. Use requests.get(..., stream=True) and read the response in bounded chunks. Reject downloads once a conservative maximum size is exceeded.
  2. Restrict sources to HTTPS and, where configuration is not intended to be arbitrary, validate destinations against an explicit hostname allowlist.
  3. Validate the HTTP status, final redirect destination, and expected calendar media type before accepting the response.
  4. Download into a temporary file in the same directory, parse and validate it, then atomically replace the active calendar using os.replace. Preserve the previous valid file if validation fails.
  5. Enforce limits on total file size, calendar component count, event count, summary length, and recurrence complexity.
  6. Reject events whose dates fall outside a defined supported range or whose duration exceeds a reasonable maximum.
  7. Avoid eagerly creating a map entry for every day of every event. Store bounded intervals and compare the requested date against those intervals instead.
  8. Remove or escape terminal control characters from external summaries before printing them.
  9. Log validation failures without including unsanitized attacker-controlled values.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (4)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file contains comments, CLI help text, and runtime output exclusively in Chinese, including the main user-facing result string and argument description. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified, which is not present in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill explicitly advertises a monthly cron-based automatic update that fetches external calendar data, but the documentation does not warn users that the skill will initiate outbound network activity on a schedule. This creates a transparency and supply-chain risk: operators may unknowingly permit recurring downloads from configurable URLs, increasing the chance of unexpected network access or ingestion of malicious/incorrect ICS data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The file explicitly sets X-APPLE-LANGUAGE:zh and X-APPLE-REGION:CN, which imposes a fixed language/locale configuration in natural-language-facing metadata. Under the policy, locale constraints should either be user-selectable or clearly documented as justified; this file provides neither.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script prints status and error messages only in Chinese (for example, '正在尝试下载' and '所有源下载均失败'). For a general-purpose skill file, hardcoding a single language without opt-in or justification can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.