Back to skill

Security audit

个人日程秘书

Security checks for vulnerabilities and agentic risk

Overview

This agenda skill is mostly a local task manager, but its dashboard instructions can let malicious pasted or inbox task text run as browser script.

Review before installing. Use it only with agenda-specific commands, and avoid processing untrusted pasted text or inbox files until the dashboard format is fixed to escape JSON for HTML script contexts, especially the literal '<' sequence, or to store data in a safer non-executable JSON container. Tightening triggers and requiring confirmation before bulk inbox processing would reduce accidental file changes.

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
SKILL.md:87
Finding

Stored Script Injection Through Untrusted Task Data Embedded in the Dashboard

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 87-95 and 123-124
Vulnerability Type: Stored script injection in an HTML script context
Risk Level: High

Vulnerable Code Snippet

markdown
1. Read unprocessed files from `inbox/`, or parse content pasted directly by the user.
2. Identify every task in the input.
3. For each task:
   - Infer the title, due date, category, and priority.
   - Create the corresponding Markdown file under `tasks/`.
4. Update `index.md` with the new tasks.
5. Update the embedded `TASKS_DATA` in `views/dashboard.html` by replacing the complete `var TASKS_DATA = ...;` line.

The corresponding dashboard data format is specified at lines 249-262:

html
<script>
  /* TASKS_DATA_START */
  var TASKS_DATA = {"generated":"YYYY-MM-DD HH:mm","tasks":[...]};
  /* TASKS_DATA_END */
</script>

The Skill also requires the data to be written as single-line compressed JSON without requiring script-context escaping:

markdown
TASKS_DATA must be written as compressed, single-line JSON.

Technical Analysis

Task titles, notes, tags, and detail entries can originate from untrusted inbox files or content pasted by a user. The Skill instructs the agent to serialize these values into JSON and place the result directly inside an executable HTML script element.

Standard JSON serialization protects JSON syntax but does not necessarily make the result safe for embedding in an HTML raw-text script context. In particular, an input containing a sequence such as:

html
</script><script>ATTACKER_CODE</script>

can cause the HTML parser to terminate the original script element before JavaScript parses the JSON. The following attacker-controlled element can then be interpreted as executable JavaScript.

The esc() helper specified at line 321 only escapes values during subsequent HTML rendering. It does not protect the initial TASKS_DATA sc ...[truncated 1563 chars]

Remediation
View remediation

Remediation Suggestions

  1. Apply context-safe serialization before inserting JSON into HTML. At minimum, replace HTML-sensitive characters after JSON serialization:

    javascript
    function safeJsonForHtml(value) {
      return JSON.stringify(value)
        .replace(/&amp;/g, "\\u0026")
        .replace(/&lt;/g, "\\u003c")
        .replace(/&gt;/g, "\\u003e")
        .replace(/\u2028/g, "\\u2028")
        .replace(/\u2029/g, "\\u2029");
    }
    

    In an actual implementation, the replacements must target the literal characters &amp;, &lt;, and &gt;, rather than already encoded HTML entities.

  2. Prefer storing the data in a non-executable element:

    html
    <script id="tasks-data" type="application/json">
      SAFE_SERIALIZED_JSON
    </script>
    

    Then parse it using:

    javascript
    var TASKS_DATA = JSON.parse(
      document.getElementById("tasks-data").textContent
    );
    

    Escaping the literal less-than character as \u003c remains necessary because HTML parsing recognizes closing script tags regardless of the script MIME type.

  3. Update the Skill instructions to explicitly require HTML script-context escaping for every generated TASKS_DATA and ARCHIVE_DATA value.

  4. Continue using esc() or equivalent safe DOM APIs when rendering values. Prefer textContent, setAttribute, and element construction over concatenating untrusted strings into innerHTML.

  5. Add regression tests containing payloads such as closing script tags, HTML tags, quotes, backslashes, Unicode separators, and ampersands. Verify that opening the generated dashboard never creates attacker-supplied elements or executes code.

  6. Add a restrictive Content Security Policy. Where practical, move trusted interaction logic into a fixed local script and disallow arbitrary inline scripts. CSP should be treated as defense in depth rather than a replacement for safe serialization.

Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill advertises very broad trigger phrases such as '处理inbox', '帮我整理一下', 'ingest', and 'update task', which can overlap with ordinary productivity requests. This increases the chance the skill is invoked in contexts the user did not intend, leading it to read and modify workspace files like inbox, tasks, index, log, and dashboard data.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The invocation guidance includes ambiguous examples like processing pasted chat logs or '帮我整理一下', which are common natural-language requests that may contain mixed content beyond task management. In this skill, accidental activation is more dangerous because the workflow authorizes bulk file reads and persistent writes, including marking inbox items processed and updating dashboard/archive artifacts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest description and argument hint are primarily in Chinese but include English phrases like “Use when”, “ingest”, “update task”, and “view dashboard”. This introduces an implicit language preference without stating that the user can choose their preferred language or locale.

Content

No source excerpt is available for this finding.