Back to skill

Security audit

sheet-process

Security checks for vulnerabilities and agentic risk

Overview

The skill appears intended to filter Tencent Docs sheets, but it needs review because it can save sheet data locally and its HTML report can embed unsafe spreadsheet content.

Install only if you trust the publisher and are comfortable granting the skill access to connected Tencent Docs sheets. Prefer JSON output for automation, avoid opening or sharing HTML reports until the escaping issue is fixed, and keep exports in a deliberate folder because they are local copies of document data.

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
scripts/smartsheet_filter.py:428
Finding
Stored HTML and JavaScript Injection in Generated Reports<![CDATA[ ## Vulnerability Details **File Location**: `scripts/smartsheet_filter.py`, lines 428–482 **Vulnerability Type**: Stored HTML injection / cross-site scripting in generated HTML reports **Risk Level**: High ### Vulnerable Code ```python html_parts = [ '<!DOCTYPE html>', '<html lang="zh-CN">', '<head>', '<meta charset="UTF-8">', '<meta name="viewport" content="width=device-width, initial-scale=1.0">', f'<title>{title}</title>', '<style>', # Static CSS omitted '</style>', '</head>', '<body>', '<div class="container">', f'<h1>{title}</h1>', f'<p class="subtitle">共筛选出 {len(results)} 条结果</p>', '<div class="stats">', f'<span class="stat-badge total">共 {len(results)} 条</span>', '</div>', '<table><thead><tr><th>#</th>', ] # 表头 for t in resolved_titles: html_parts.append(f'<th>{t}</th>') html_parts.append('</tr></thead><tbody>') # 行 for i, row in enumerate(results, 1): html_parts.append(f'<tr><td>{i}</td>') for t in resolved_titles: val = row.get(t, "") if val.startswith("http"): val = f'<a href="{val}" target="_blank">{val}</a>' else: val = val.replace("<", "&lt;").replace(">", "&gt;") html_parts.append(f'<td>{val}</td>') ``` ### Technical Analysis The HTML generator interpolates several untrusted or externally influenced values directly into HTML: - The report `title` is inserted into both `<title>` and `<h1>` without escaping. - Column titles from the processed spreadsheet are inserted into `<th>` elements without escaping. - Cell values beginning with `http` are inserted into an `href` attribute and anchor body without any attribute escaping. - Other cell values only replace `<` and `>`. This is incomplete HTML encoding and does not provide safe contextual handling for all output locations. The URL branch is particularly dangerous because a malicious spreadsheet value can begin with `http` while containing a qu ...[truncated 2392 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Apply contextual HTML escaping to every dynamic value. Use `html.escape(value, quote=True)` for report titles, headings, cell text, link text, and attribute values. 2. Validate URLs before creating links. Parse values with `urllib.parse.urlparse` and permit only an explicit allowlist of schemes, preferably `https`. Values that fail validation should be rendered as escaped plain text. 3. Avoid manually concatenating HTML where possible. Use a template engine configured with automatic escaping, such as Jinja2 with autoescape enabled. 4. Separate link validation from output encoding. URL validation determines whether a value may be used as a link, while HTML escaping prevents it from breaking out of its output context. Both controls are required. 5. Add `rel="noopener noreferrer"` to links opened with `target="_blank"`. 6. Add regression tests covering: - Quotes in URL values. - Event-handler injection attempts. - HTML tags and encoded tags in titles and column headings. - `javascript:`, `data:`, and malformed URL schemes. - Ampersands, quotation marks, apostrophes, and angle brackets. A hardened implementation could follow this pattern: ```python import html from urllib.parse import urlparse def escape_html(value) -> str: return html.escape(str(value), quote=True) def is_allowed_url(value: str) -> bool: try: parsed = urlparse(value) return parsed.scheme.lower() == "https" and bool(parsed.netloc) except (TypeError, ValueError): return False safe_title = escape_html(title) html_parts.append(f"<title>{safe_title}</title>") html_parts.append(f"<h1>{safe_title}</h1>") for column_title in resolved_titles: html_parts.append(f"<th>{escape_html(column_title)}</th>") for column_title in resolved_titles: raw_value = str(row.get(column_title, "")) safe_value = escape_html(raw_value) if is_allowed_url(raw_value): html_parts.append( f'<td><a h ...[truncated 179 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (13)

Vague Triggers

High
Confidence
96% confidence
Finding
Defaulting to atomic mode when no trigger phrase is present creates overly broad activation, so ordinary conversation about tables may unintentionally launch a skill that enumerates documents, reads sheet metadata, and produces files. In this skill, the risk is amplified because later steps can access connected Tencent Docs resources and invoke code-backed processing once the user continues the flow.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The trigger phrase "表格过滤" is ambiguous and lacks clear context boundaries, so it may be invoked by casual phrasing that does not actually intend this specific skill. While less broad than "表格处理," accidental activation still creates unnecessary exposure to document operations and may cause confusing or unintended data handling in connected sheets.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill embeds executable code paths and writes output files, but it does not declare any explicit tool scope such as allowed-tools or permissions. That mismatch weakens containment and review, because a broadly activated skill could invoke shell/file-write capable behavior without clear upfront authorization boundaries.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The atomic-mode trigger phrases are generic everyday terms such as '表格筛选/表格处理/表格过滤', which are likely to appear in normal user requests unrelated to this specific skill. This increases accidental invocation risk and, combined with the skill's document access and code execution behavior, can lead to unintended processing of connected spreadsheet data.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
Returns:
            list[dict]: [{"sheet_id": "xxx", "title": "xxx"}, ...]
        """
        result = subprocess.run(
            [
                "python3", "tencentdocs.py", "tdoc_call",
                "tencent-docs", "smartsheet.list_tables",
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
This code invokes an external tool via subprocess and passes the user-supplied file_id to a Tencent Docs service, which constitutes a network-backed data access operation. Although the module docstring describes functionality, there is no explicit warning or disclosure that the tool will contact Tencent Docs and retrieve remote spreadsheet metadata.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The _tdoc_call method is the central path for remote service access and is used to fetch table lists, fields, and records from Tencent Docs. There is no confirmation prompt or user-visible warning indicating that spreadsheet contents may be retrieved from a remote service when this method is used.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def _tdoc_call(self, service: str, tool: str, args: dict) -> dict:
        """调用腾讯文档 MCP 接口"""
        result = subprocess.run(
            [
                "python3", "tencentdocs.py", "tdoc_call",
                service, tool, json.dumps(args, ensure_ascii=False)
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Vague Triggers

Low
Confidence
84% confidence
Finding
The trigger phrase "表格过滤" is ambiguous and lacks clear context boundaries, so it may be invoked by casual phrasing that does not actually intend this specific skill. While less broad than "表格处理," accidental activation still creates unnecessary exposure to document operations and may cause confusing or unintended data handling in connected sheets.

Description-Behavior Mismatch

Low
Confidence
85% confidence
Finding
The skill can write filtered remote spreadsheet contents to an arbitrary local path via output_path, which may persist sensitive business data on disk outside the original document system. In an agent environment, this increases data-exfiltration and unintended local disclosure risk, especially if downstream prompts or users can influence the destination path.

Missing User Warnings

Low
Confidence
89% confidence
Finding
Writing filtered spreadsheet results to a caller-controlled path can cause sensitive remote data to be stored locally without safeguards, increasing confidentiality and retention risk. In shared or automated environments, this can expose business data to other local users, backup systems, or later workflows that were not intended to access it.

Missing User Warnings

Low
Confidence
89% confidence
Finding
The HTML export persists filtered remote data to disk and may additionally create clickable links, making the resulting file easy to share or reopen outside the original access controls. This is dangerous because users may not realize they have created an unmanaged local copy of potentially sensitive spreadsheet content.

Description-Behavior Mismatch

Low
Confidence
73% confidence
Finding
The CLI workflow exposes local export behavior that is broader than simple in-memory filtering and can silently create HTML/JSON files from remote spreadsheet data. While not inherently malicious, this widens the attack surface in agent or automation contexts because persistence to disk may occur without clear operator awareness.

Static analysis

No suspicious patterns detected.