Back to skill

Security audit

Personal Health Archive Trend

Security checks for vulnerabilities and agentic risk

Overview

The skill claims sensitive health records stay local, but the included public payment backend can accept, process, and temporarily retain health-record data.

Review this skill before installing or using it with real health records. Only use it if you are comfortable with the merchant backend and payment setup, and do not send health data to the payment endpoint unless the publisher fixes the privacy mismatch, enforces a strict payment-only request schema, disables production mock mode, and documents key handling and retention clearly.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
mch-demo-adult/server.py:684
Finding

Payment Endpoint Accepts and Retains Health Data Contrary to the Declared Privacy Boundary

Content
View full analysis
str: # Compatibility path for requests containing health records. if data.get("profile") or data.get("reports"): return build_adult_record(data) skill = data.get("skill") or "personal-health-archive-trend" ``` The HTTP handler reads the complete request body and passes the parsed data to this function: ```python length = int(self.headers.get("Content-Length", 0) or 0) raw = self.rfile.read(length) if length else b"{}" try: data = json.loads(raw or b"{}") except Exception: data = {} ``` During initial order creation, the generated result is retained in the process-wide order store: ```python with _lock: _orders[out_trade_no] = { "paid": False, "content": execute_business(data), } ``` Consequently, a request containing a name, birth date, measurements, and medical reports is processed remotely and converted into an identifiable health record. The generated record remains in server memory until process termination or replacement. Base64 operations elsewhere in the file are used for payment signatures, payment payloads, and callback cryptography. No separate encoded health-data exfiltration channel was identified. The confirmed issue is the direct acceptance and processing of health data by the remote endpoint. ### At ...[truncated 1124 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
mch-demo-adult/server.py:87
Finding

Fail-Open Mock Mode Allows Payment Verification Bypass

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
mch-demo-adult/server.py:766
Finding

Paid Orders Can Be Replayed and Are Not Bound to an Immutable Fulfillment Request

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
mch-demo-adult/server.py:748
Finding

Unbounded Request Body Reading Enables Memory and Worker Exhaustion

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
mch-demo-adult/requirements.txt:1
Finding

Open-Ended Dependency Constraints Produce Non-Reproducible Builds

Content
View full analysis
=2.31 cryptography>=42.0 ``` The Docker build installs whatever versions satisfy those constraints at build time: ```dockerfile COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt ``` As a result, rebuilding the same source can install materially different third-party code. The audit found no evidence that the named packages are typosquatted or currently malicious; the risk is the absence of reproducible, reviewed dependency resolution. ### Attack Path 1. The image is rebuilt at a later date. 2. Package resolution selects newer transitive or direct dependency versions. 3. Those versions have not necessarily undergone project-specific security review or compatibility testing. 4. Newly introduced vulnerable or compromised dependency code is incorporated into the production image. 5. The dependency executes with the application process's privileges when imported or invoked. ### Impact Assessment The eventual impact depends on the behavior of an unreviewed dependency release. Because the Dockerfile does not define a non-root `USER`, dependency code currently runs as the container's default root user, increasing impact inside the container. Possible consequences include: - Build non-reproducibility. - Unexpected runtime behavior. - Introduction of known or newly disclosed vulnerabilities. - Supply-chain compromise affecting payment credentials or network communication within the container. No active malicious dependency was confirmed during this static audit. ]]>
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (50)

Tainted flow: 'path' from os.environ.get (line 164, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · mch-demo-adult/server.py (reported line 158)May include surrounding context.

python
"Content-Type": "application/json",
        "Accept": "application/json",
    }
    r = requests.post(WX_BASE + path, data=body.encode(), headers=headers, timeout=20)
    r.raise_for_status()
    return r.json().get("code_url", "")

Tainted flow: 'path' from os.environ.get (line 164, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · mch-demo-adult/server.py (reported line 169)May include surrounding context.

python
"Authorization": _wx_authorization("GET", path, ""),
        "Accept": "application/json",
    }
    r = requests.get(WX_BASE + path, headers=headers, timeout=20)
    r.raise_for_status()
    return r.json().get("trade_state", "")

Tainted flow: 'path' from os.environ.get (line 164, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · mch-demo-adult/server.py (reported line 199)May include surrounding context.

python
"Authorization": _wx_authorization("GET", path, ""),
        "Accept": "application/json",
    }
    r = requests.get(WX_BASE + path, headers=headers, timeout=20)
    r.raise_for_status()
    return r.json().get("trade_state", "")

Tainted flow: 'headers' from os.environ.get (line 195, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · mch-demo-adult/server.py (reported line 295)May include surrounding context.

python
sign_str = f"POST\n{PREORDER_PATH}\n{ts}\n{nonce}\n{payment_required}\n"
    l1["signature"] = _sign(_load_sh_key(), sign_str)
    headers = {"Content-Type": "application/json", "Accept": "application/json"}
    r = requests.post(PREORDER_URL, data=json.dumps(l1).encode(), headers=headers, timeout=20)
    r.raise_for_status()
    data = r.json()
    return data.get("payment_code") or json.dumps(l1)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill is presented as a purely local health-processing tool, but its workflow requires communication with an external payment-validation endpoint and operationally behaves like a paid networked service. For a health-data skill, this mismatch is dangerous because users and agents may rely on the privacy claim when deciding whether sensitive medical documents are safe to use, even though the real execution model introduces external dependencies and a broader attack surface.

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 · .gitignore (reported line 2)May include surrounding context.

text
# 复制本文件为 .env 并填入真实值(不要提交 .env 到 git)

# ===== 微信支付侧(商户平台获取)=====
MCH_ID=1900000001

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 · mch-demo-adult/.dockerignore (reported line 1)May include surrounding context.

text
# 复制本文件为 .env 并填入真实值(不要提交 .env 到 git)

# ===== 微信支付侧(商户平台获取)=====
MCH_ID=1900000001

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 · mch-demo-adult/.env.example (reported line 1)May include surrounding context.

text
# 复制本文件为 .env 并填入真实值(不要提交 .env 到 git)

# ===== 微信支付侧(商户平台获取)=====
MCH_ID=1900000001

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The Caddyfile configures a public HTTPS endpoint on a real domain and proxies traffic to a local service, which directly contradicts the claim that sensitive health data is processed only locally and never exposed externally. Even if no explicit upload code is shown here, publishing the app on an internet-reachable interface creates a remote access path for protected health data and expands the attack surface substantially.

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 · README.md (reported line 15)May include surrounding context.

md
container_name: mch-demo-adult
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "8081:8080"
    volumes:

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 · mch-demo-adult/Dockerfile (reported line 13)May include surrounding context.

dockerfile
container_name: mch-demo-adult
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "8081:8080"
    volumes:

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 · mch-demo-adult/docker-compose.yml (reported line 7)May include surrounding context.

yaml
container_name: mch-demo-adult
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "8081:8080"
    volumes:

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 · mch-demo-adult/docker-compose.yml (reported line 15)May include surrounding context.

yaml
container_name: mch-demo-adult
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "8081:8080"
    volumes:

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 · mch-demo-adult/server.py (reported line 17)May include surrounding context.

python
container_name: mch-demo-adult
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "8081:8080"
    volumes:

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 · mch-demo-adult/部署-群晖NAS.md (reported line 55)May include surrounding context.

md
container_name: mch-demo-adult
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "8081:8080"
    volumes:

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 · mch-demo-adult/部署说明.md (reported line 23)May include surrounding context.

md
container_name: mch-demo-adult
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "8081:8080"
    volumes:

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

This configuration mounts a WeChat Pay private key file from the host into the container. Even though it is read-only, compromise of the application or container could still allow an attacker to read and exfiltrate the private key, enabling payment request signing or broader impersonation depending on how the key is used.

Content

Scanner excerpt · mch-demo-adult/docker-compose.yml (reported line 11)May include surrounding context.

yaml
ports:
      - "8081:8080"
    volumes:
      # 把微信支付私钥挂进容器,路径与 .env 的 PRIVATE_KEY_PATH 一致
      - "./apiclient_key.pem:/Users/weiwu/cert/1749040075_20260805_cert/apiclient_key.pem:ro"
      # SkillHub 开发者私钥(PEM),对应 .env 的 SKILLHUB_PRIVATE_KEY_FILE
      - "./skillhub_private_key.pem:/app/skillhub_private_key.pem:ro"

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

This line mounts the SkillHub developer private key into the application container, creating a direct path for key disclosure if the container, app, or local environment is compromised. A developer signing key is especially sensitive because theft can enable unauthorized signing, impersonation, or abuse of the associated integration.

Content

Scanner excerpt · mch-demo-adult/docker-compose.yml (reported line 13)May include surrounding context.

yaml
volumes:
      # 把微信支付私钥挂进容器,路径与 .env 的 PRIVATE_KEY_PATH 一致
      - "./apiclient_key.pem:/Users/weiwu/cert/1749040075_20260805_cert/apiclient_key.pem:ro"
      # SkillHub 开发者私钥(PEM),对应 .env 的 SKILLHUB_PRIVATE_KEY_FILE
      - "./skillhub_private_key.pem:/app/skillhub_private_key.pem:ro"
      # 微信支付公钥(公钥模式验签用),对应 .env 的 WX_PUB_KEY_FILE / WX_PUB_KEY_ID
      - "./wechat_pub_key.pem:/app/wechat_pub_key.pem:ro"

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 · mch-demo-adult/server.py (reported line 42)May include surrounding context.

python
from cryptography.x509 import load_pem_x509_certificate


def _load_dotenv(path=".env"):
    """健壮加载 .env,支持无引号多行 PEM 私钥。"""
    try:
        with open(path, encoding="utf-8") as f:

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 · mch-demo-adult/server.py (reported line 78)May include surrounding context.

python
from cryptography.x509 import load_pem_x509_certificate


def _load_dotenv(path=".env"):
    """健壮加载 .env,支持无引号多行 PEM 私钥。"""
    try:
        with open(path, encoding="utf-8") as f:

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The docstring says the paid endpoint does not receive or consume health data, yet the implementation processes such data whenever present. In a health-data context this mismatch is dangerous because it defeats privacy expectations, weakens informed consent, and can cause sensitive medical information to be transmitted to a remote service unintentionally.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill description promises local-only processing of highly sensitive adult health records, but the server explicitly accepts profile/reports and generates the health archive remotely. This creates a privacy and trust-boundary violation: users and calling agents may send medical data under the false assumption it never leaves the device.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation says health data is processed fully locally and not uploaded externally, but these deployment steps explicitly publish the service on a public domain and accept Internet-originated buyer requests and payment callbacks. Even if the application runs on the user's NAS, exposing AI and payment endpoints over the public Internet creates external transmission and remote attack surface that contradicts the privacy claim and can lead to sensitive health data disclosure or unauthorized access.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
76% confidence
Finding

This section states that apiclient_key.pem is mounted into the container and its certificate path is aligned with .env while the deployment is exposed via Cloudflare Tunnel. Referencing live payment key material in an Internet-exposed deployment context increases the risk of private key compromise through misconfigured mounts, weak file permissions, backup/sync leakage, or container compromise, which could enable fraudulent payment operations or forged requests.

Content

Scanner excerpt · mch-demo-adult/部署-群晖NAS.md (reported line 83)May include surrounding context.

md
## 你的实际方案:Cloudflare Tunnel(已打通,采用此方式)
- **不需要**路由器开 80/443,也**不需要**群晖自己签证书。Cloudflare 在边缘终止 TLS,NAS 上只把容器 8080 暴露给本机 `localhost` 即可。
- 容器已在 NAS 跑起来并发布 `8080` 到本机(docker-compose 已加 `apiclient_key.pem` 挂载,证书路径与 .env 一致)。
- 在 **Cloudflare Zero Trust → Access → Tunnels → 你的 tunnel → Public Hostname** 添加一条:
  - Subdomain:`mch` Domain:`1001058.xyz` Type:`HTTP` URL:`http://localhost:8080`
  - (子域名随意,只要和 `.env` 的 `PAY_NOTIFY_URL` 对应;当前已设为 `https://mch.1001058.xyz`)

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill metadata claims health data is processed entirely locally and not uploaded externally, but the deployment guide explicitly requires a public HTTPS backend and remote payment callback endpoints. In the context of adult health archives, this discrepancy is dangerous because users may disclose sensitive medical information under a false local-only privacy claim while requests are actually sent to a network-accessible service.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.