Back to skill

Security audit

Mentx Doctor 医疗助手

Security checks for vulnerabilities and agentic risk

Overview

This medical skill has a coherent purpose, but it can automatically send sensitive health information to an external service without enough user consent, scoping, or local data safeguards.

Install only if you are comfortable sending health questions and medical files to Mentx.com. Before use, confirm what data is sent, how it is retained, and who can access it; avoid broad automatic triggering for casual health mentions, avoid storing API keys in shell startup files when possible, and do not run this on shared machines until the /tmp report storage and task ID validation issues are fixed.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mentx-api.sh:111
Finding
Path Traversal Enables Unauthorized File Read and Deletion<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mentx-api.sh`, lines 111-130 **Vulnerability Type**: Unvalidated path component and path traversal **Risk Level**: High ### Vulnerable Code ```bash check_task_status() { local task_id="$1" local status_file="$TEMP_DIR/${task_id}.status" local result_file="$TEMP_DIR/${task_id}.result" if [ ! -f "$status_file" ]; then echo "{\"status\": \"not_found\", \"message\": \"任务不存在\"}" return fi local status=$(cat "$status_file") if [ "$status" = "completed" ]; then # 读取结果并返回 local result=$(cat "$result_file") echo "{\"status\": \"completed\", \"result\": $result}" # 清理临时文件 rm -f "$status_file" "$result_file" else echo "{\"status\": \"running\", \"message\": \"报告正在生成中,请稍候...\"}" fi } ``` ### Technical Analysis The `task_id` argument is supplied by the caller and inserted directly into two filesystem paths: ```bash "$TEMP_DIR/${task_id}.status" "$TEMP_DIR/${task_id}.result" ``` No allowlist validation, canonicalization, or containment check is performed. A task ID containing sequences such as `../` can therefore cause the paths to resolve outside `/tmp/mentx-doctor`. The function reads the selected status file. If its content is `completed`, it reads the corresponding result file, returns its contents, and deletes both files. The issue affects the `check` action directly and can also be reached through the polling functionality. The attack is constrained to paired paths whose final names end in `.status` and `.result`, but this does not prevent unauthorized access where such paired files exist or can be prepared. ### Attack Path 1. A local attacker identifies or creates a readable target pair such as `/tmp/target.status` and `/tmp/target.result`. 2. The attacker places `completed` in `/tmp/target.status`. 3. The attacker invokes: ```bash ./scripts/mentx-api.sh check "../target" ``` 4. The generated paths resolve as follows: ```te ...[truncated 790 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce a strict allowlist before using a task ID: ```bash if [[ ! "$task_id" =~ ^mentx_[0-9]+_[0-9]+$ ]]; then echo '{"status":"error","message":"Invalid task ID"}' return 1 fi ``` 2. Reject path separators and traversal components explicitly. 3. Resolve each candidate path to a canonical path and verify that it remains under the expected task directory. 4. Store a server-generated mapping between opaque task IDs and internally created file paths rather than deriving paths from caller input. 5. Avoid deleting files based solely on an externally supplied identifier. 6. Check file ownership and reject symbolic links before reading or deleting any task file. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mentx-api.sh:13
Finding
Predictable Shared Temporary Files Expose Sensitive Medical Reports<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mentx-api.sh`, lines 13-14, 51-60, and 98-107 **Vulnerability Type**: Insecure temporary-file creation and symlink exposure **Risk Level**: High ### Vulnerable Code ```bash # 临时目录 TEMP_DIR="/tmp/mentx-doctor" mkdir -p "$TEMP_DIR" ``` ```bash # 生成任务 ID generate_task_id() { echo "mentx_$(date +%s)_$$" } # 异步启动报告生成任务(后台运行,立即返回) start_report_task() { local user_message="$1" local user_id="$2" local files_json="$3" local task_id=$(generate_task_id) local result_file="$TEMP_DIR/${task_id}.result" local status_file="$TEMP_DIR/${task_id}.status" ``` ```bash # 后台执行 API 调用 ( echo -e "${BLUE}[任务 $task_id] 开始生成医疗报告...${NC}" response=$(curl -s -X POST "https://developer.mentx.com/v1/chat/completions" \ -H "Authorization: Bearer $MENTX_API_KEY" \ -H "Content-Type: application/json" \ -d "$request_body") # 保存结果到文件 echo "$response" > "$result_file" echo "completed" > "$status_file" echo -e "${BLUE}[任务 $task_id] 报告已生成,保存到:$result_file${NC}" ) & ``` ### Technical Analysis The script uses a fixed, shared directory under `/tmp` and creates it without explicitly restrictive permissions. It also does not set a restrictive process `umask`. Task filenames are generated from the current Unix timestamp and process ID. These values are predictable or can often be observed by another local user. Files are created using ordinary shell redirection, which: - Does not guarantee exclusive atomic creation. - Follows pre-existing symbolic links. - Does not verify file ownership or type. - Applies permissions according to the ambient `umask`. - Allows interaction with names in a shared, predictable directory. The result file contains the full response from the medical API and may therefore hold highly sensitive health information. The initial status write and subsequent result write can both target attacker-prepared filesystem objects if symbolic li ...[truncated 1373 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Set restrictive permissions before creating temporary resources: ```bash umask 077 ``` 2. Create a private per-process directory atomically: ```bash TEMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/mentx-doctor.XXXXXX") chmod 700 "$TEMP_DIR" ``` 3. Register a cleanup trap: ```bash trap 'rm -rf -- "$TEMP_DIR"' EXIT HUP INT TERM ``` 4. Generate task identifiers with cryptographically strong random data rather than timestamps and process IDs. 5. Create files atomically and exclusively; do not overwrite pre-existing paths. 6. Use mechanisms that reject symbolic links, and verify each file is a regular file owned by the current account before reading, writing, or deleting it. 7. If asynchronous calls must survive the parent process, use a dedicated private state directory with strict ownership and permissions rather than a globally predictable `/tmp` path. 8. Define a retention policy so medical reports are securely removed after retrieval or timeout. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mentx-api.sh:64
Finding
Untrusted Input Is Interpolated Directly into JSON Requests<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mentx-api.sh`, lines 64-95 **Vulnerability Type**: JSON injection and malformed request construction **Risk Level**: Medium ### Vulnerable Code ```bash # 构建请求体 local request_body if [ -z "$files_json" ] || [ "$files_json" = "[]" ]; then request_body=$(cat <<EOF { "agent": "AI-GP-ReportAgent", "userId": "$user_id", "messages": [ { "role": "user", "content": "$user_message" } ], "stream": false } EOF ) else request_body=$(cat <<EOF { "agent": "AI-GP-ReportAgent", "userId": "$user_id", "messages": [ { "role": "user", "content": "$user_message" } ], "files": $files_json, "stream": false } EOF ) fi ``` ### Technical Analysis The script constructs JSON through direct shell interpolation. The following values are not encoded or validated before insertion: - `user_id` - `user_message` - `files_json` A message or user ID containing quotation marks, backslashes, line breaks, or control characters can terminate or modify the intended JSON string. The `files_json` value is inserted as a raw JSON fragment without validation that it is an array or that its objects contain only expected fields. This is not shell command injection because the interpolated values remain data within the here-document and `curl` argument. It is nevertheless JSON injection: attacker-controlled input can create malformed requests or alter the structure and semantics of the body submitted to the external API. ### Attack Path 1. An attacker supplies a crafted message, user identifier, or raw `files_json` argument. 2. The value contains JSON syntax that closes the intended string or inserts additional properties. 3. The here-document produces a malformed or structurally modified JSON document. 4. The script submits that document to: ```text https://developer.mentx.com/v1/chat/completions ``` 5. Depending on the API parser's duplicate-key and ...[truncated 847 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Construct the request with a JSON-aware encoder such as `jq`: ```bash request_body=$(jq -n \ --arg agent "AI-GP-ReportAgent" \ --arg user_id "$user_id" \ --arg message "$user_message" \ '{ agent: $agent, userId: $user_id, messages: [{role: "user", content: $message}], stream: false }') ``` 2. Parse and validate `files_json` separately: ```bash if ! jq -e 'type == "array"' >/dev/null 2>&1 <<<"$files_json"; then echo "Invalid files JSON" >&2 return 1 fi ``` 3. Validate every file object against an allowlist of expected fields and data types. 4. Pass validated file data using `jq --argjson` rather than raw string interpolation. 5. Enforce reasonable input-length limits for messages, identifiers, and file arrays. 6. Treat API validation failures separately from successful report completion and avoid marking malformed or error responses as successfully completed reports. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (13)

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Content
# mentx@doctor 技能

医疗辅助决策报告生成助手 - 为用户提供医疗健康问题的辅助分析与参考报告。

## 快速开始

### 1. 配置 API 密钥

```bash
# 临时设置(当前会话)
export MENTX_API_KEY="your_api_key_here"

# 永久设置(添加到 ~/.bashrc 或 ~/.zshrc)
echo 'export MENTX_API_KEY="your_api_key_here"' >> ~/.bashrc
source ~/.bashrc
```

获取密钥:https://developer.mentx.com/

### 2. 验证配置

```bash
cd ~/.openclaw/workspace/skills/mentx-doctor
./scripts/mentx-api.sh check_key
```

### 3. 使用方式

**在对话中直接描述健康问题**,技能会自动触发:

- 纯文字描述:`"最近头晕乏力,有高血压家族史"`
- 图文混合:上传医学影像图片 + 文字描述

### 4. 紧急症状处理

如检测到胸痛、呼吸困难等紧急症状,会立即提示就医。

---

## 文件结构

```
mentx-doctor/
�
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill describes accepting symptom text, medical documents, images, and then asynchronously sending them to a professional medical API, but it does not clearly warn users that sensitive health data will be transmitted off-platform. In a healthcare context, omission of explicit disclosure and consent is a serious privacy and compliance risk, especially when files and potentially identifying data are involved.

Missing User Warnings

High
Confidence
94% confidence
Finding
The script uploads user-provided files to an external medical API and provides no built-in disclosure, consent gate, or privacy warning at the point of transfer. Because these files may contain sensitive medical records, transmitting them off-system without explicit user awareness can create serious privacy, compliance, and data-governance risk.

Missing User Warnings

High
Confidence
95% confidence
Finding
The script sends user medical messages, identifiers, and optionally attached file references to an external API without explicit notice in the execution flow. In a medical-assistant context, this increases the sensitivity of the transmission because both free-text symptoms and user IDs may constitute personal or regulated health information.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The README says users can directly describe health problems and that the skill will "automatically trigger," using very broad natural-language examples. In an agent environment, such loose activation criteria can overlap with ordinary conversation and cause unintended invocation on sensitive medical content, which may route private data to an external service or produce unsolicited medical guidance.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
“仅限中国大陆用户使用”属于语言/地域范围限制的自然语言策略约束,但 README 未说明用户可选择其他地区模式,也未解释该限制的合规或业务必要性。按规则,这类未提供 opt-in 或明确正当依据的地域限制应视为潜在政策违规。

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The skill states that the initial 'emotional comfort' phase excludes medical analysis, but later instructs the agent to ask symptom-triage questions and suggest actions like drinking warm water, resting, and breathing exercises. In a medical context, these are health-related recommendations and can blur the boundary between emotional support and clinical guidance, increasing the risk that users rely on unvalidated advice before a professional review is available.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger conditions are broad enough to activate on ordinary conversation about health, stress, reports, or common symptoms, which can cause inadvertent collection and forwarding of sensitive medical information. Because this skill invokes a backend medical API, over-triggering increases privacy exposure and the chance that users receive medical-style handling when they did not clearly request it.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The boundary statement says emotional comfort contains no health advice, diagnosis hints, or health suggestions, yet the examples direct the agent to gather symptom details and provide self-care guidance. This inconsistency is dangerous because implementers and users may misunderstand what the system is permitted to do, leading to unsupervised pseudo-triage in a high-stakes medical setting.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The statement "仅限中国大陆用户使用" is a natural-language locale restriction that excludes users by region, but the document does not provide user choice or a clear compliance justification for the limitation. Under the policy rule, forced locale or region constraints without opt-in or documented necessity should be flagged.

External Transmission

Medium
Category
Data Exfiltration
Content
(
    echo -e "${BLUE}[任务 $task_id] 开始生成医疗报告...${NC}"
    
    response=$(curl -s -X POST "https://developer.mentx.com/v1/chat/completions" \
      -H "Authorization: Bearer $MENTX_API_KEY" \
      -H "Content-Type: application/json" \
      -d "$request_body")
Confidence
91% confidence
Finding
This code performs deliberate external transmission of user-supplied medical content to a third-party service. While external API use is expected for this skill's purpose, the medical context makes the transfer more dangerous because highly sensitive data leaves the local environment and is handled by a remote provider.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
Comments and all user-visible messages are written in Chinese, and the script does not offer any option to select another language or locale. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy concern.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The comment says the enhanced version supports '等待期间可提供情绪陪伴' (provide emotional companionship while waiting). In practice, the polling logic only sleeps, checks status, and emits progress messages to stderr; there is no logic that provides supportive or conversational output during waiting.

Static analysis

No suspicious patterns detected.