Back to skill

Security audit

data-skill

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its data-analysis purpose, but its chart server can expose local project data more broadly than users are told.

Review before installing. Use this only in a trusted local workspace, avoid sensitive datasets unless the chart server is fixed to bind to 127.0.0.1 and serve only approved output files, remove wildcard CORS, and add a clear stop/timeout mechanism. Treat Baidu map/geocoding as an external-data path and pin dependencies before production use.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/server.py:63
Finding

Project Root Exposed Through an Unauthenticated Network Server

Content
View full analysis

Vulnerability Details

File Location: scripts/server.py, lines 63-70
Vulnerability Type: Unrestricted network binding and excessive file-serving scope
Risk Level: High

Vulnerable Code

python
def run_server_forever(port, base_dir):
    """Run the server synchronously."""
    os.chdir(base_dir)
    # Save server info
    os.makedirs(os.path.join(base_dir, 'tmp'), exist_ok=True)
    with open(get_server_info_file(), 'w') as f:
        json.dump({'port': port}, f)
        
    handler = CustomHTTPRequestHandler
    with socketserver.TCPServer(("", port), handler) as httpd:

Technical Analysis

The process changes its working directory to the project root and uses SimpleHTTPRequestHandler, which serves files underneath the current working directory. The server then binds to an empty host address, equivalent to all available network interfaces rather than loopback only.

Although ensure_server_running() returns a URL using 127.0.0.1, that returned URL does not constrain the listening socket. Hosts capable of reaching the machine on the selected port may request project files without authentication.

The project root may contain workspace.db, config.txt, generated reports, chart configurations, cached geographic data, source files, and other business data. Serving the complete root therefore exceeds the legitimate requirement to expose generated chart HTML and static ECharts assets.

Attack Path

  1. A user generates a chart, causing the HTTP server to start on a port between 8000 and 8099.
  2. The service listens on all network interfaces.
  3. An attacker on a reachable network discovers the open port through scanning or local network observation.
  4. The attacker requests sensitive paths such as /workspace.db, /config.txt, /references/geo_cache.json, or files under /outputs/.
  5. SimpleHTTPRequestHandler returns accessible files without authentication.
  6. The att ...[truncated 564 chars]
Remediation
View remediation

Remediation Suggestions

  1. Bind the service explicitly to loopback:
    python
    with socketserver.TCPServer(("127.0.0.1", port), handler) as httpd:
    
  2. Do not change the serving directory to the project root. Use a dedicated public directory containing only generated chart HTML and approved static assets.
  3. Implement an allowlist for URL paths and reject requests for databases, configuration files, dotfiles, source files, and metadata.
  4. Add an unpredictable per-session access token if browser access is required.
  5. Add security tests confirming that /workspace.db, /config.txt, and directory listings cannot be retrieved.
  6. Run the server with minimal filesystem permissions and disable directory listing.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/server.py:50
Finding

Wildcard CORS Enables Browser-Based Reading of Local Files

Content
View full analysis

Vulnerability Details

File Location: scripts/server.py, lines 50-53
Vulnerability Type: Permissive cross-origin resource sharing configuration
Risk Level: High

Vulnerable Code

python
class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    def end_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
        super().end_headers()

Technical Analysis

The handler adds Access-Control-Allow-Origin: * to every response. Consequently, scripts running on any website are permitted by the browser to read responses from this server.

This weakness is especially significant because the same server serves the project root without authentication. A malicious webpage visited by the user can probe likely localhost ports and, when the server is active, issue cross-origin requests for predictable files. Wildcard CORS allows the attacking page to inspect the response body rather than being blocked by the browser's same-origin policy.

The issue is not limited to chart content because the response header is applied universally to all files handled by SimpleHTTPRequestHandler.

Attack Path

  1. The local chart server is running on a port between 8000 and 8099.
  2. The user visits an attacker-controlled website.
  3. JavaScript on that website probes http://127.0.0.1:8000 through http://127.0.0.1:8099.
  4. After locating the service, the script requests predictable paths such as /workspace.db or /config.txt.
  5. The server returns Access-Control-Allow-Origin: *.
  6. The browser permits the malicious page to read the response.
  7. The page transmits the recovered content to the attacker's remote server.

Impact Assessment

This configuration allows any web origin to use the user's browser as a bridge to the local chart server. In combination with project-root serving, ...[truncated 189 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the CORS header if cross-origin access is not strictly required.
  2. If CORS is necessary, allow only a narrowly defined trusted origin rather than *.
  3. Apply CORS only to approved chart resources, never to arbitrary files.
  4. Add Vary: Origin when dynamically validating allowed origins.
  5. Combine the CORS correction with loopback-only binding and a restricted document root.
  6. Consider requiring a random session token and rejecting requests that lack it.

T06 · System Persistence

Warning
Location
scripts/server.py:90
Finding

Detached HTTP Server Persists After the Invoking Task Ends

Content
View full analysis

Vulnerability Details

File Location: scripts/server.py, lines 90-103
Vulnerability Type: Uncontrolled detached background process
Risk Level: Medium

Vulnerable Code

python
if not port:
    import subprocess
    port = find_free_port()
    
    # Start this very script as a background process using the --daemon flag
    cmd = [sys.executable, os.path.abspath(__file__), "--daemon", "--port", str(port)]
    
    if sys.platform == 'win32':
        subprocess.Popen(cmd, 
                         creationflags=subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.DETACHED_PROCESS,
                         stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    else:
        subprocess.Popen(cmd, 
                         start_new_session=True,
                         stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

Technical Analysis

Chart generation starts the HTTP server as a detached process. On Windows it uses detached process flags, while on other platforms it creates a new session. The process runs serve_forever() and has no inactivity timeout, parent-lifecycle coupling, or explicit shutdown mechanism.

This behavior allows the server to remain active after the agent operation or terminal task that created it has completed. Suppressing standard output and error output also makes the process less visible and complicates monitoring and troubleshooting.

The server does not establish operating-system startup persistence across a reboot, but it does create cross-task and potentially cross-session persistence for as long as the host remains running.

Attack Path

  1. The user requests chart generation.
  2. ensure_server_running() launches server.py as a detached background process.
  3. The original chart-generation process exits, but the detached server continues running.
  4. The user assumes the operation has completed and no service remains exposed.
  5. At a ...[truncated 613 chars]
Remediation
View remediation

Remediation Suggestions

  1. Keep the server attached to the invoking task and terminate it when chart viewing is complete.
  2. Add a short inactivity timeout and automatically call shutdown() after the timeout.
  3. Provide an explicit stop command that reads a securely stored process identifier and terminates only the expected server.
  4. Couple the server lifecycle to the parent process where supported.
  5. Record the process identifier and validate both the process identity and bound address before reusing an existing server.
  6. Avoid suppressing all error output; write lifecycle events to a controlled local log.
  7. Bind only to 127.0.0.1 and restrict the served directory even while the process is active.

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Dependencies Create Supply-Chain and Reproducibility Risk

Content
View full analysis

Vulnerability Details

File Location: requirements.txt, lines 1-5
Vulnerability Type: Unconstrained third-party dependency installation
Risk Level: Medium

Vulnerable Code

text
pandas
openpyxl
matplotlib
seaborn
thefuzz

The documented installation command in README.md is:

bash
pip install -r requirements.txt

Technical Analysis

None of the listed packages has a version constraint or integrity hash. Each installation can therefore resolve to different package and transitive-dependency versions depending on installation time and package-index state.

This prevents reproducible builds and makes it difficult to ensure that the installed code is the same code reviewed during the audit. If a future release or transitive dependency is compromised, withdrawn, or introduces a security regression, the documented installation command can retrieve it automatically.

No evidence was found that the package names are typosquatted or currently malicious. The confirmed issue is the absence of version and integrity controls, not proof that the present upstream packages are compromised.

Attack Path

  1. An attacker compromises a listed dependency, one of its transitive dependencies, or the package distribution channel.
  2. A malicious or vulnerable release becomes the version selected by the unconstrained resolver.
  3. A user follows the documented installation procedure.
  4. pip downloads the newly selected package rather than a previously reviewed version.
  5. Package installation or later import executes compromised code with the privileges of the user running the skill.

Impact Assessment

A compromised dependency could execute arbitrary Python code with the installing or running user's privileges. Depending on those privileges, it could access local datasets, configuration files, API credentials, and other files available to the account. Even without malicious compromise, u ...[truncated 107 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin every direct dependency to a reviewed version.
  2. Generate a lock file that also constrains transitive dependencies.
  3. Use package hashes and install with pip --require-hashes.
  4. Retrieve packages only from an explicitly configured trusted package index.
  5. Run dependency vulnerability and license scans in continuous integration.
  6. Review and test dependency updates before changing the lock file.
  7. Install dependencies in an isolated virtual environment using a non-privileged account.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (409)

Harmful Content Injection

Critical
Category
Prompt Injection
Confidence
70% confidence
Finding

This content may contain harmful instructions that could cause physical harm if followed. CRITICAL: Review carefully before use.

Content

Scanner excerpt · references/prompts/scatter/master_painter_color_choices_throughout_history.md (reported line 3585)May include surrounding context.

md
"        by Ilya Repin",
      "Le Pont de l'Anglois by Vincent van Gogh",
      "Die Brcke von l'Anglois by Vincent van Gogh",
      "Boats at Sea, Saintes-Maries-de-la-Mer by Vincent van Gogh",
      "Schneebedeckte Felder vor Arles by Vincent van Gogh",
      "Stilleben mit Oleander by Vincent van Gogh",
      "Le Pont de l'Anglois by Vincent van Gogh",
      "Die Romanleserin by Vincent van Gogh",
      "Montagne Sainte-Victoire by Paul Czanne",
      "Obstgarten mit Zypressen by Vincent van Gogh",
      "Park von Arles by Vincent van Gogh",

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是本地数据分析处理能力,核心应围绕数据导入、清洗、SQL/Python 运算、表格处理和报告生成。但实际代码是一个前端地图扩展库 bmap.min.js,用于把 ECharts 图表叠加到百度地图上,处理经纬度到像素坐标转换、地图样式设置、拖拽缩放事件以及 coordinate system 注册。这与所宣称的办公数据分析/本地代码执行能力不一致,且代码显式依赖百度地图 API(BMap),属于未声明的地图可视化与外部地图资源集成能力。因此该描述与代码行为存在明显不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是一个面向办公场景的数据分析处理 Skill,核心能力应围绕表格数据处理、数据库查询、清洗分析与报告输出。实际代码仅是一个前端 JavaScript 地图数据文件,检查 echarts 是否存在并调用 registerMap('china', ...) 注册中国地图边界数据。它的主要用途是为图表库提供地理底图,不执行任何办公数据分析任务,也不体现所声明的本地代码执行、SQLite、Excel/CSV 处理等功能。因此代码行为与声明的主要用途明显不符,属于实质性不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的是一个本地数据分析处理助手,其核心应当体现数据导入、数据库查询、清洗分析或报告生成等能力。但实际代码是 ECharts/ZRender 的压缩前端库文件,只负责图表绘制和交互渲染的基础能力。虽然声明中提到“支持生成图表”,因此图表库可被视为某个辅助组件,但当前提供的代码片段并不能支撑该 Skill 的主要宣称功能,且其主要用途与“本地代码执行做数据分析”明显不同。因此该代码与声明存在实质性不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

声明描述的是一个通用、本地、注重隐私的数据分析处理 Skill,覆盖导入、清洗、查询、提取、合并拆分、报告生成和图表等广泛办公数据处理任务。但提供的代码块只实现了其中很窄的一部分:从 SQLite 执行 SQL 查询并生成 ECharts HTML 图表。更重要的是,代码包含未在描述中体现的外部能力:为地图图表读取 BAIDU_AK,并调用百度地图 API 做地址地理编码,这与“本地代码执行模式”“保障数据隐私安全”的表述存在张力,因为地址数据可能被发送到第三方服务。虽然图表生成本身属于声明范围,但代码的实际主功能比声明狭窄很多,且存在未声明的外部网络访问与凭据使用,因此应判定为描述与行为不完全一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

声明描述的是一个通用办公数据分析 Skill,核心能力应围绕结构化数据处理与分析展开;但提供的代码仅实现了一个 CLI 工具,将指标名称和描述追加写入 references/metrics.md。其主要用途是维护业务指标定义文档,最多可作为后续 SQL 生成的辅助上下文准备工具,但这只是间接支持,不是声明中的主要功能。因此代码行为与声明用途存在明显且实质性的偏差,应判定为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述强调的是面向最终用户的数据分析与办公文件处理能力,如导入清洗表格数据、跨表查询、图表和报告生成。但实际代码并未执行任何数据导入、清洗、查询、SQLite/SQL 操作,也未处理 Excel/CSV 文件。它的核心功能是扫描一个文档中的图表类型并生成 ECharts 配置模板 JSON,属于开发资源生成/模板构建工具。虽然与“图表”领域略有相关,但其主要目的和实现行为与声明的办公数据分析助手明显不一致,因此应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 53)May include surrounding context.

md
2. We have a powerful template-based rendering engine. Use the built-in `scripts/chart_generator.py` script.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 71)May include surrounding context.

md
2. We have a powerful template-based rendering engine. Use the built-in `scripts/chart_generator.py` script.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 99)May include surrounding context.

md
python scripts/data_cleaner.py --db workspace.db --days 30

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 106)May include surrounding context.

md
2. Use the built-in script `scripts/metrics_manager.py` to append the metric:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 108)May include surrounding context.

md
2. Use the built-in script `scripts/metrics_manager.py` to append the metric:

Ae5

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Instruction-capable artifact exceeds whole-file semantic analysis limits

Content

No source excerpt is available for this finding.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · references/support_original.md (reported line 4606)May include surrounding context.

, 0)], endValue: dataAxis[Math.min(params.dataIndex + zoomSize / 2, data.length - 1)] }); });

text

柱状图标签旋转
Bar Label Rotation
## 案例

const posList = [ 'left', 'right', 'top', 'bottom', 'inside', 'insideTop', 'insideLeft', 'insideRight', 'insideBottom', 'insideTopLeft', 'insideTopRight', 'insideBottomLeft', 'insideBottomRight' ]; app.configParameters = { rotate: { min: -90, max: 90 }, align: { options: { left: 'left', center: 'center', right: 'right' } }, verticalAlign: { options: { top: 'top', middle: 'middle', bottom: 'bottom' } }, position: { options: posList.reduce(function (map, pos) { map[pos] = pos; return map; }, {}) }, distance: { min: 0, max: 100 } }; app.config = { rotate: 90, align: 'left', verticalAlign: 'middle', position: 'insideBottom', distance: 15, onChange: function () { const labelOption

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README presents all user-facing instructions and usage guidance in Chinese, and does not indicate that the skill is region-specific or provide an opt-in language/locale choice. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
84% confidence
Finding

The documented workflow promotes keeping imported data and derived tables in local persistent storage for ongoing analysis and undo capability. Without strict tenancy boundaries and lifecycle management, persistent state can leak prior users' data into later sessions or make sensitive business data recoverable beyond its intended use.

Content

Scanner excerpt · README.md (reported line 35)May include surrounding context.

md
1. **导入拦截**:收到文件后,Agent 会调用内置的 `scripts/data_importer.py` 脚本,将数据清洗、规整后安全写入本地 `workspace.db` (SQLite)。
2. **本地探查**:Agent 使用 SQL 探查表结构(Schema)和部分统计信息,而不是读取所有行。
3. **非破坏性操作**:当收到修改指令时,Agent 会生成 SQL 或 Python 脚本在本地运行。并且必须通过创建新表或视图(如 `CREATE TABLE v2 AS SELECT...`)来执行,确保原始数据不被污染。
4. **结果输出**:根据要求,将处理好的数据重新导出为干净的 Excel,或生成可视化图表。

## 安装方式

Session Persistence

Medium
Category
Rogue Agent
Confidence
84% confidence
Finding

The documented workflow promotes keeping imported data and derived tables in local persistent storage for ongoing analysis and undo capability. Without strict tenancy boundaries and lifecycle management, persistent state can leak prior users' data into later sessions or make sensitive business data recoverable beyond its intended use.

Content

Scanner excerpt · README.md (reported line 35)May include surrounding context.

md
1. **导入拦截**:收到文件后,Agent 会调用内置的 `scripts/data_importer.py` 脚本,将数据清洗、规整后安全写入本地 `workspace.db` (SQLite)。
2. **本地探查**:Agent 使用 SQL 探查表结构(Schema)和部分统计信息,而不是读取所有行。
3. **非破坏性操作**:当收到修改指令时,Agent 会生成 SQL 或 Python 脚本在本地运行。并且必须通过创建新表或视图(如 `CREATE TABLE v2 AS SELECT...`)来执行,确保原始数据不被污染。
4. **结果输出**:根据要求,将处理好的数据重新导出为干净的 Excel,或生成可视化图表。

## 安装方式

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The document states the skill 'strictly' adheres to a Local Code Execution paradigm, but later instructions include automatic local HTTP serving and built-in geocoding capabilities for map charts. That creates an intent-level contradiction because the documentation frames the system as strictly local while describing behavior that may open service endpoints or depend on non-local coordinate lookup.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest and workflow emphasize keeping data local and preserving privacy, but the chart-generation procedure says the script will start a local HTTP server and also mentions geocoding capabilities for map charts. Even if the server is local, exposing data through a served endpoint and invoking geocoding goes beyond the straightforward 'local SQL/Python + SQLite' privacy-focused description and weakens the stated privacy boundary.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The markdown instructs running a cleaner script that removes tables and metadata not accessed in the last 30 days. Although this is triggered by maintenance or user request, the description does not include a clear warning that the action is destructive/irreversible or advise confirmation/backup before deletion.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file’s operative instructions are written in Chinese and directly prescribe how the assistant should perform the task, with no indication that the user can choose another language or that the skill is intentionally restricted to a Chinese-language context. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The prompt is written entirely in Chinese and instructs the model in Chinese without any indication that the user may choose another language or locale. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file's operative instructions are presented in Chinese, which effectively forces a specific language for users consuming or invoking this skill. The policy allows locale constraints only when the skill offers user choice or clearly justifies the constraint, neither of which appears here.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
assets/echarts/echarts.min.js:45