Back to skill

Security audit

数据分析师skill

Security checks for vulnerabilities and agentic risk

Overview

This data-analysis skill is coherent, but its generated HTML reports can render untrusted dataset text as active browser content.

Install only if you are comfortable with the skill reading the datasets you name and leaving local report, chart, and summary files behind. Avoid using it on untrusted datasets until HTML escaping is fixed, because malicious text inside a dataset could execute when the generated report is opened in a browser.

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/report_builder.py:272
Finding

Stored HTML and JavaScript Injection in Generated Analysis Reports

Content
View full analysis
list: """Summary statistics for categorical columns.""" if not cat_cols: return [] results = [] for col in cat_cols: series = df[col] vc = series.value_counts() results.append({ 'column': col, 'count': int(series.count()), 'unique': int(series.nunique()), 'missing': int(series.isna().sum()), 'top_value': str(vc.index[0]) if len(vc) > 0 else None, 'top_count': int(vc.iloc[0]) if len(vc) > 0 else 0, 'top_pct': round(vc.iloc[0] / series.count() * 100, 1) if len(vc) > 0 and series.count() > 0 else 0, }) return results ``` The resulting column names and categorical values are inserted directly into the HTML report: ```python rows = '\n'.join(f''' {s['column']} {s['count']:,} {s['unique']} {s['missing']} {s['top_value']} {s['top_count']:,} {s['top_pct']}% ''' for s in summary) ``` Other report fields, including `dataset_name`, numeric column names, correlation feature names, and audit messages, are also interpolated into HTML without context-aware escaping. ### Technical Analysis The report builder uses Python formatted strings to construct HTML. Values originating from an analyzed dataset are treated as trusted markup instead of untrusted text. No HTML escaping or sanitization is applied before these values are placed inside element content or the re ...[truncated 2600 chars]
Remediation
View remediation
str: return escape(str(value), quote=True) ``` Use this helper for dataset names, column names, categorical values, audit messages, chart labels, and correlation feature names. 2. Prefer a templating engine with automatic escaping enabled rather than constructing the entire document with formatted strings. For example: ```python from jinja2 import Environment, select_autoescape env = Environment( autoescape=select_autoescape( enabled_extensions=('html', 'xml'), default_for_string=True ) ) template = env.from_string(template_source) report_html = template.render(report_data) ``` Do not mark dataset-derived content as safe HTML. 3. Keep markup generated by the application separate from untrusted report data. Escape values at the final rendering boundary even if earlier processing stages appear to sanitize them. 4. Add a restrictive Content Security Policy to the generated report, for example: ```html ``` Eliminating inline scripts and event-handler execution substantially limits the impact of any missed escaping location. 5. Validate chart embedding separately. Restrict embedded files to expected image formats such as PNG, JPEG, SVG only after appropriate sanitization, and GIF. Derive MIME types from an allowlist rather than directly trusting arbitrary file extensions. 6. Add regression tests using malicious dataset names, column names, categorical values, and audit messages. Tests should verify that strings such as `
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 (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

该代码块的主要用途是图表可视化,且文件名也表明是 visualizer 模块。它接收已经存在的 DataFrame 和部分EDA结果,输出保存到目录中的PNG图像。这与声明的“覆盖完整数据分析管线”的能力范围明显不符。虽然可视化属于声明中的一部分,但当前代码块仅覆盖其中的子功能,缺少声明中多项核心能力,因此描述对该代码块而言明显过度宽泛,存在实质性描述-行为不匹配。

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill advertises very broad trigger phrases such as 'analyze data', 'data analysis', and their Chinese equivalents, which are common user requests and can cause the skill to activate in many unrelated contexts. Over-broad activation increases the chance that the workflow processes unintended user data or overrides more appropriate, narrower skills, expanding the attack surface and creating opportunities for prompt-routing abuse.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises executable scripts that read user-supplied files and generate HTML reports/charts, but it does not declare any explicit tool scope such as file-read and file-write permissions. That mismatch reduces transparency and weakens policy enforcement, making it easier for a caller or host agent to invoke file system operations without clear user awareness or least-privilege boundaries.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are very broad, including common requests like 'analyze data' and '生成数据报告', which increases the chance that the skill auto-activates in contexts the user did not intend. Because the skill can read files and write artifacts, overly broad activation can cause unintended access to local data or creation of output files without sufficiently explicit user consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill states it generates HTML reports and saves charts to a charts/ subdirectory, but the description does not prominently warn users that it writes files to disk. This can surprise users, create confidentiality or persistence risks on shared systems, and leave behind sensitive derived artifacts from private datasets.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The report builder interpolates untrusted values such as dataset_name and many fields from audit_results and eda_results directly into HTML element bodies and attributes without escaping. If an attacker can control CSV headers, categorical values, issue text, or the dataset name, they can inject HTML/JavaScript into the generated report; when a user opens the local HTML file, the script executes in the browser context, enabling stored XSS against report viewers.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The generated report hard-codes <html lang="zh-CN">, which imposes a specific locale on all output regardless of user preference or dataset context. Under the policy, locale-specific behavior should offer user choice or include a clear justified constraint, neither of which is present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
64% confidence
Finding

The skill metadata and title are primarily in Chinese while the main descriptive sections are in English, with no statement about supported languages or user choice. This can create an implicit language/locale policy ambiguity rather than clearly offering language selection or documenting the intended audience.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The business rules use "CNY" in natural-language descriptions and units, which imposes a China-specific currency assumption. The file does not indicate that this configuration is region-specific or that users can choose another locale/currency, which may conflict with language/locale policy expectations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The e-commerce example also fixes the currency to "CNY" and describes amounts in that locale without any note that this is an example or region-limited configuration. This can be read as forcing a specific locale assumption rather than offering a user choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The font initialization logic explicitly prioritizes Chinese-capable fonts such as 'Microsoft YaHei', 'SimHei', 'Noto Sans SC', and 'KaiTi', which imposes a locale-specific presentation choice in generated charts. The file does not offer a user language/locale choice or explain why a Chinese locale preference is required, which matches the language/locale policy concern.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.