Back to skill

Security audit

Auto Data Analysis Claw

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its data-analysis purpose, but its HTML report feature can turn untrusted business data into executable browser content.

Review this skill before installing if you will use HTML output or process data from other people. Prefer Markdown output for untrusted data, avoid opening generated HTML reports from untrusted inputs in a privileged browser session or shared authenticated origin, and keep input/output paths limited to a working folder to reduce accidental exposure or overwrite of sensitive financial files.

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/report_generator.py:113
Finding

Stored HTML and JavaScript Injection in Generated Reports

Content
View full analysis

Vulnerability Details

File Location: scripts/report_generator.py, lines 113-163
Vulnerability Type: Unescaped HTML generation from attacker-controlled report configuration and data
Risk Level: Medium

Vulnerable Code

python
body = f"<h1>{title}</h1>\n"
if metadata:
    body += f"<p class='meta'>生成时间: {metadata.get('generated_at', datetime.now().strftime('%Y-%m-%d %H:%M'))}</p>\n"
    if metadata.get("period"):
        body += f"<p class='meta'>数据周期: {metadata['period']}</p>\n"

for section in sections:
    body += f"<h2>{section['title']}</h2>\n"
    content = section.get("content", "")
    if isinstance(content, dict):
        # KPI 卡片
        if all(isinstance(v, dict) and "value" in v for v in content.values()):
            for k, v in content.items():
                body += f"<div class='kpi'><div class='value'>{v.get('value', 'N/A')}</div><div class='label'>{k}</div></div>\n"
        else:
            body += _dict_to_html_table(content)
    elif isinstance(content, list) and content and isinstance(content[0], dict):
        body += _list_to_html_table(content)
    else:
        body += f"<p>{content}</p>\n"
    if section.get("insight"):
        body += f"<div class='insight'>💡 <strong>洞察</strong>: {section['insight']}</div>\n"

html = f"""<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="utf-8"><title>{title}</title><style>{css}</style></head>
<body>{body}</body></html>"""

def _dict_to_html_table(d: dict) -> str:
    rows = ""
    if all(isinstance(v, dict) for v in d.values()):
        sub_keys = list(dict.fromkeys(k for v in d.values() for k in v.keys()))
        rows += "<tr><th>指标</th>" + "".join(f"<th>{k}</th>" for k in sub_keys) + "</tr>"
        for k, v in d.items():
            rows += "<tr><td>" + k + "</td>" + "".join(f"<td>{v.get(sk, '')}</td>" for sk in sub_keys) + "</tr>"
    else:
        for k, v in d.items():
            rows += f"<tr><td>{k}</td><td>{v}</td></tr>"
    return f"<table>{rows}</table>"

de
...[truncated 2490 chars]
Remediation
View remediation

Remediation Suggestions

  • Escape every dynamic value before inserting it into HTML. Use html.escape(str(value), quote=True) for report titles, metadata, section titles, content, insights, KPI fields, table keys, headers, and cells.
  • Prefer a template engine with automatic HTML escaping enabled rather than constructing markup through string interpolation.
  • If rich HTML content is an intentional feature, sanitize it with a strict allowlist-based HTML sanitizer. Remove scripts, event-handler attributes, active embedded elements, unsafe URL schemes, and dangerous CSS.
  • Apply context-appropriate escaping, including HTML text escaping and HTML attribute escaping where applicable.
  • Add a restrictive Content Security Policy when reports are served, for example by disallowing inline scripts and limiting external connections. This should be defense in depth rather than a substitute for escaping.
  • Add regression tests using payloads in every dynamic field, including:
    • <script>alert(1)</script>
    • <img src=x onerror=alert(1)>
    • <svg onload=alert(1)>
    • malformed markup intended to escape table or paragraph contexts
  • Consider opening generated reports under an isolated origin or sandboxing them when they contain data from untrusted sources.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

声明描述的是一个端到端的数据分析与报表技能,涵盖对财务报表和业务数据的分析、挖掘、指标计算及多维比较分析。但给出的代码块只负责把预先提供的sections内容写成Markdown或HTML报表,附带简单的表格和KPI展示逻辑。代码没有读取或解析财务报表数据源进行分析,没有任何统计、聚合、同比环比、趋势、差异、清洗或挖掘算法实现。虽然“生成专业报表”与声明中的一部分相符,但声明的核心能力明显超出实际代码行为,因此存在实质性描述与行为不匹配。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill instructs the agent to read input files, write cleaned outputs, and generate reports, but it does not declare any explicit tool scope such as allowed tools or path restrictions. In a data-analysis skill that operates on user-supplied file paths and output paths, this can lead to overly broad file system access and accidental reading or overwriting of unintended files if the runtime grants defaults that are wider than expected.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger list includes broad phrases like '看看数据' and '分析一下', which may cause the skill to activate in contexts the user did not intend. Because the skill can perform file reads/writes and invoke analysis/reporting workflows, overbroad activation increases the chance of unintended processing of sensitive business or financial data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

整个技能文件以中文定义名称、描述、流程和输出要求,但未说明这是区域性/合规性限制,也未给出用户可选择语言的机制。根据语言/locale 政策,默认强制特定语言且无用户选择属于自然语言策略风险。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document requires report output in Chinese conventions throughout, including Chinese headings and locale-specific number formatting such as the ¥ prefix and the use of "万" and "亿". This is a natural-language locale policy concern because it imposes a specific language/format without any opt-in or documented scope limitation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This Python file contains natural-language strings that force a specific language/locale for the skill experience, including the module description and CLI help text. Under the policy, locale constraints should either provide user opt-in/choice or be clearly documented as intentionally region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This Python file contains natural-language strings entirely in Chinese, including the module description, CLI help text, status messages, and an explicit HTML lang="zh-CN" setting. The policy scope covers all file types, and there is no opt-in or documented justification for forcing a specific language/locale.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The HTML generator directly interpolates untrusted fields such as title, section titles, content, table cells, and insights into HTML without escaping. If user-supplied financial or business data contains HTML or JavaScript, opening the generated report in a browser can trigger script execution, turning a reporting feature into an active content delivery vector.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file is entirely written in Chinese and provides no indication that language selection is optional or that the content is intentionally limited to a Chinese-speaking context. Under the policy rule, forcing a specific language without user opt-in is a natural-language locale violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.