Back to skill

Security audit

Kids Points V2

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real kids-points tracker, but it needs Review because it handles family chat and ledger data with under-scoped LLM, database, network, and credential behavior.

Install only if you are comfortable with a chat bot that can modify a family points ledger, send message text to a configured external LLM, and run local subprocesses with inherited environment credentials. Before use, restrict it to approved Feishu chats, use a dedicated LLM key, remove broad environment inheritance, replace LLM-generated SQL with fixed parameterized queries, bind the dashboard to localhost or add authentication, avoid the curl | sh installer, and do not use chmod 666 for serial access.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (6)

T03 · Remote Payload Retrieval and Execution

Error
Location
extensions/dashboard/docs/dependencies.md:96
Finding

Mutable Remote Installer Is Downloaded and Executed Without Verification

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
extensions/dashboard/code/server/server.py:43
Finding

Unauthenticated Dashboard Exposes Family Ledger Data on All Network Interfaces

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
runtime/pipeline.py:908
Finding

LLM-Generated SQL Is Executed After an Insufficient Prefix Check

Content
View full analysis
dict: from .db import execute_query sql = query_data.get("sql", "") if not sql: raise ValueError("semantic 查询缺少 SQL") # Security check: only allow SELECT sql_upper = sql.strip().upper() if not sql_upper.startswith("SELECT"): raise ValueError(f"不允许的 SQL 操作:{sql[:50]}") rows = execute_query(conn, sql) ``` ```python def execute_query(conn: sqlite3.Connection, sql: str) -> list[dict]: """Execute a read-only query generated by the LLM.""" rows = conn.execute(sql).fetchall() return [_row_to_dict(row) for row in rows] ``` Results are returned to the chat: ```python if result.get("type") == "semantic": rows = result.get("rows", []) # ... for i, row in enumerate(rows[:20], 1): parts = [] for k, v in row.items(): # ... parts.append(str(v)) lines.append(f"{i}. {' | '.join(parts)}") ``` ### Technical Analysis Untrusted Feishu message text is interpolated into a prompt that asks the LLM to generate SQL. The generated SQL is then executed directly against the application database. The only enforcement is a string-prefix check requiring the statement to begin with `SELECT`. This is not a security boundary. It does not: - Restrict queries to the `transactions` table. - Restrict selected columns. - Prevent access to `audit_log`, `proce ...[truncated 2071 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
extensions/dashboard/code/server/data_source.py:19
Finding

Predictable Shared Temporary Cache File Allows Ledger Disclosure and Symlink-Based Overwrite

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
runtime/llm_config.py:26
Finding

Entire Hermes Secret Environment Is Loaded and Inherited by Redirectable Child Processes

Content
View full analysis
None: if not path.exists(): return try: for raw in path.read_text(encoding="utf-8").splitlines(): line = raw.strip() if not line or line.startswith("#") or "=" not in line: continue k, v = line.split("=", 1) k = k.strip() v = v.strip().strip('"').strip("'") if k and k not in os.environ: os.environ[k] = v except OSError: pass _load_hermes_env(_HERMES_ENV_PATH) ``` The JavaScript handler permits runtime redirection and inherits the complete environment: ```javascript const V2_RUNTIME_DIR = process.env.KIDS_POINTS_RUNTIME_DIR || path.join(__dirname, 'runtime'); const V2_CLI = path.join(V2_RUNTIME_DIR, 'cli.py'); py = spawn('python3', [V2_CLI, message], { cwd: V2_RUNTIME_DIR, env: { ...process.env }, timeout: 30000, }); ``` The Python handler has equivalent behavior: ```python V2_RUNTIME_DIR = os.environ.get( "KIDS_POINTS_RUNTIME_DIR", str(Path(__file__).parent.parent / "runtime") ) result = subprocess.run( ["python3", "cli.py", message], cwd=V2_RUNTIME_DIR, capture_output=True, text=True, timeout=30, env={**os.environ}, ) ``` ### Technical Analysis The LLM configuration loader imports every key-value assignment from `~/.hermes/.env` into the current process, rather than reading only the one API-key variable selected by configuration. Both dispatch handlers then pass the complete process environment to child Python processes. This exceeds the minimum pr ...[truncated 1665 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
extensions/dashboard/code/server/requirements.txt:1
Finding

Unpinned Dependencies and Unverified Vendor Components Make Builds Non-Reproducible

Content
View full analysis
=3.0 flask-sock>=0.6 watchdog>=6.0 websocket-client>=1.0 ``` The Arduino instructions also install packages without exact versions: ```bash arduino-cli lib install "ESP32 HUB75 LED MATRIX PANEL DMA Display" arduino-cli lib install "U8g2 for Adafruit GFX" arduino-cli lib install "ArduinoJson" arduino-cli lib install "Adafruit GFX Library" ``` The dependency documentation identifies an externally supplied ZIP without integrity metadata: ```text ESP32 HUB75 LED MATRIX PANEL DMA Display | 2.0.7 Source: ZIP supplied by the vendor ``` ### Technical Analysis The Python requirements use open-ended lower bounds rather than exact versions or hashes. A fresh installation may therefore select a future release that was not included in this audit. The Arduino installation commands similarly omit exact versions despite the surrounding documentation discussing version requirements. The vendor-supplied matrix library is not accompanied by an authenticated source URL, checksum, signature, or vendored reviewed copy. This prevents users from verifying that they received the same component used by the developer. No specific dependency was proven malicious during this static audit. The vulnerability is the absence of reproducible and verifiable dependency controls, which creates an avoidable supply-chain attack surface. ### Attack Path 1. A dependency publisher account, package repository, or vendor delivery path is compromised. 2. A newer malicious package version or modified ZIP is published. 3. A user performs installation using the documented commands. 4. The package manager selects the newer compatible version because only a minimum version is specified, or the user installs the unveri ...[truncated 494 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (92)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The static finding indicates the code may support LLM-generated SQL for semantic querying and adjustment workflows that are not disclosed in the skill description. Undocumented model-to-SQL behavior is particularly sensitive because it can affect data integrity and query scope, and users evaluating a simple points bot would not expect an AI-mediated database query surface.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The static finding indicates the code may support LLM-generated SQL for semantic querying and adjustment workflows that are not disclosed in the skill description. Undocumented model-to-SQL behavior is particularly sensitive because it can affect data integrity and query scope, and users evaluating a simple points bot would not expect an AI-mediated database query surface.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The static finding indicates the code may support LLM-generated SQL for semantic querying and adjustment workflows that are not disclosed in the skill description. Undocumented model-to-SQL behavior is particularly sensitive because it can affect data integrity and query scope, and users evaluating a simple points bot would not expect an AI-mediated database query surface.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The static finding indicates the code may support LLM-generated SQL for semantic querying and adjustment workflows that are not disclosed in the skill description. Undocumented model-to-SQL behavior is particularly sensitive because it can affect data integrity and query scope, and users evaluating a simple points bot would not expect an AI-mediated database query surface.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The static finding indicates the code may support LLM-generated SQL for semantic querying and adjustment workflows that are not disclosed in the skill description. Undocumented model-to-SQL behavior is particularly sensitive because it can affect data integrity and query scope, and users evaluating a simple points bot would not expect an AI-mediated database query surface.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · extensions/dashboard/README.md (reported line 96)May include surrounding context.

验证:

bash
curl http://localhost:8080/api/health
curl http://localhost:8080/api/dashboard | python3 -m json.tool

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · extensions/dashboard/docs/INDEX.md (reported line 124)May include surrounding context.

md
arduino-cli monitor -p /dev/ttyUSB0 -c baudrate=115200

# 看 server 数据
curl http://YOUR_SERVER_IP:8080/api/dashboard | python3 -m json.tool

# 加积分
python3 \

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · extensions/dashboard/docs/server-code.md (reported line 227)May include surrounding context.

md
arduino-cli monitor -p /dev/ttyUSB0 -c baudrate=115200

# 看 server 数据
curl http://YOUR_SERVER_IP:8080/api/dashboard | python3 -m json.tool

# 加积分
python3 \

Chaining Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

The shell pipeline into sh removes the opportunity for users to review downloaded content and is a classic command-chaining pattern that amplifies supply-chain compromise risk. In this skill context, the file is operational setup documentation, so readers are likely to copy-paste the command directly on a development or service host.

Content

Scanner excerpt · extensions/dashboard/docs/dependencies.md (reported line 96)May include surrounding context.

bash
# 装 (一次性)
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh

# 加 ESP32 core
arduino-cli core update-index

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
94% confidence
Finding

chmod 666 is an abusive parameter choice because it grants universal access rather than the minimum needed to solve the serial-port issue. In this hardware-development context, the risk is somewhat bounded to local access, but it is still dangerous because it normalizes insecure troubleshooting steps and could expose connected device I/O to other users or malware on the host.

Content

Scanner excerpt · extensions/dashboard/docs/esp32-code.md (reported line 216)May include surrounding context.

串口打不开 (CH340 USB 死锁)

  • 完全拔 USB 30 秒+
  • 换 USB 口
  • sudo chmod 666 /dev/ttyUSB0

编译失败 - 库找不到

bash

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
94% confidence
Finding

Recommending sudo chmod 666 /dev/ttyUSB0 is dangerous because it combines root execution with an overbroad permission change on a live device interface. This can be exploited by any local user or malware on the host to gain persistent unrestricted access to the serial endpoint, enabling unauthorized flashing, command injection over serial consoles, or capture of sensitive device output.

Content

Scanner excerpt · extensions/dashboard/docs/pitfalls.md (reported line 207)May include surrounding context.

esptool --chip esp32 --port /dev/ttyUSB0 --baud 115200 write_flash ...

串口权限

sudo chmod 666 /dev/ttyUSB0

text

### 永久 lesson

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The docstring says this function performs a read-only query, but the implementation does not enforce read-only behavior at all. That mismatch is dangerous because other components may trust the helper as safe for LLM-produced SQL, when in reality it can execute INSERT, UPDATE, DELETE, DROP, ATTACH, or PRAGMA statements that modify or expose the database.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · runtime/llm_config.py (reported line 26)May include surrounding context.

python
_PROJECT_ROOT = Path(__file__).parent
_CONFIG_PATH = _PROJECT_ROOT / "config.yaml"
_HERMES_AUTH_PATH = Path.home() / ".hermes" / "auth.json"
_HERMES_ENV_PATH = Path.home() / ".hermes" / ".env"


# ─── ~/.hermes/.env 自动加载 ─────────────────────────────────────────────────

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · runtime/llm_config.py (reported line 29)May include surrounding context.

python
_HERMES_ENV_PATH = Path.home() / ".hermes" / ".env"


# ─── ~/.hermes/.env 自动加载 ─────────────────────────────────────────────────
# Hermes 把真实 API key 存在 ~/.hermes/.env;auth.json 的 credential_pool
# 条目通过 source: "env:<YOUR_API_KEY_VAR>" 引用它。本项目代码在普通 shell
# 下不会自动 source 这个文件,所以在 import 时主动把里面声明的 KEY 类变量

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · runtime/llm_config.py (reported line 49)May include surrounding context.

python
_HERMES_ENV_PATH = Path.home() / ".hermes" / ".env"


# ─── ~/.hermes/.env 自动加载 ─────────────────────────────────────────────────
# Hermes 把真实 API key 存在 ~/.hermes/.env;auth.json 的 credential_pool
# 条目通过 source: "env:<YOUR_API_KEY_VAR>" 引用它。本项目代码在普通 shell
# 下不会自动 source 这个文件,所以在 import 时主动把里面声明的 KEY 类变量

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · runtime/llm_config.py (reported line 75)May include surrounding context.

python
_HERMES_ENV_PATH = Path.home() / ".hermes" / ".env"


# ─── ~/.hermes/.env 自动加载 ─────────────────────────────────────────────────
# Hermes 把真实 API key 存在 ~/.hermes/.env;auth.json 的 credential_pool
# 条目通过 source: "env:<YOUR_API_KEY_VAR>" 引用它。本项目代码在普通 shell
# 下不会自动 source 这个文件,所以在 import 时主动把里面声明的 KEY 类变量

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
96% confidence
Finding

The explicit copy of os.environ into the subprocess exposes all available environment variables, including credentials noted in the comment, to a child process triggered by chat messages. In the context of a messaging skill that can be steered via runtime-path configuration, this significantly increases blast radius by making secret harvesting trivial for any compromised or substituted cli.py.

Content

Scanner excerpt · scripts/handle_feishu.py (reported line 61)May include surrounding context.

python
capture_output=True,
            text=True,
            timeout=30,
            env={**os.environ},  # 继承 ~/.hermes/.env (LLM API key) 等
        )
    except subprocess.TimeoutExpired:
        return "⚠️ V2 处理超时 (30s), 请重试"

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The inline comment confirms the subprocess is intended to inherit credentials such as LLM API keys from the host environment. For a kids-points chat handler, this is more dangerous than usual because low-trust user input can trigger execution of a secondary program, and any compromise of that program or its selected runtime path exposes those secrets.

Content

Scanner excerpt · scripts/handle_feishu.py (reported line 61)May include surrounding context.

python
capture_output=True,
            text=True,
            timeout=30,
            env={**os.environ},  # 继承 ~/.hermes/.env (LLM API key) 等
        )
    except subprocess.TimeoutExpired:
        return "⚠️ V2 处理超时 (30s), 请重试"

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill description is written entirely in Chinese and instructs usage through Chinese-language examples, but it does not state that the skill is region-specific or offer any 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.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises capabilities that imply access to environment variables, local files, network, and shell execution, but the manifest does not declare any tool scope or permission boundaries. This weakens reviewability and least-privilege controls, making it easier for a skill with broad runtime access to perform sensitive actions that users and platform policy cannot easily constrain.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill says it uses LLM semantic analysis but does not clearly warn that user chat content is sent to an external LLM API. For a family-oriented tool handling children's activity records, this creates a meaningful privacy and consent risk because users may unknowingly transmit sensitive household data to a third party.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The code is explicitly designed to process all group and direct chats ('全量响应') and forwards message contents to downstream runtime logic without any consent, allowlist, or scope checks. In a chat-integrated skill that may handle children’s data and semantic analysis, broad always-on collection increases privacy exposure and the risk of processing sensitive conversations unintentionally.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest describes a children’s points-management skill with SQLite storage, semantic analysis, CLI interface, and Feishu support. While invoking internal logic is expected, using Node.js to launch an OS-level subprocess introduces a broader execution capability than the stated business purpose requires, especially since the handler could have invoked library code directly instead of granting process-execution behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The entire skill documentation is written in Chinese, including setup, warnings, and operational instructions, with no indication that alternative language support is available. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation unless the constraint is explicitly justified as region-specific.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest description focuses on children's points management, SQLite, LLM semantic analysis, CLI, and Feishu chat support. This file documents additional behavior: an ESP32 LED-matrix dashboard with Wi‑Fi connectivity, 30-second polling, WebSocket-triggered refresh, OTA, and auto-reconnect, which materially broadens the described system behavior.

Content

No source excerpt is available for this finding.