Back to skill

Security audit

Pediatric Health Record

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent paid cloud health-record service, but its included server has payment-bypass, replay, and sensitive-data retention weaknesses that warrant Review before install.

Review before installing or deploying. Use only if you are comfortable sending child health information to the merchant cloud service and using the WeChat payment flow. Before production use, disable fail-open mock behavior, require complete credentials, bind orders to request/session state, add expiration and deletion for health records, enforce request size/rate limits, pin dependencies, and protect payment keys with a proper secrets mechanism.

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/server.py:95
Finding

Fail-Open Mock Mode Allows Payment and Callback Verification Bypass

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
mch-demo/server.py:654
Finding

Paid Order Numbers Are Replayable and Not Bound to Request Content

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
mch-demo/server.py:691
Finding

Sensitive Pediatric Health Records Are Retained Without Expiration

Content
View full analysis
由「儿科健康档案建立器」依据你提供的数据自动生成") L.append("") L.append("## 一、基本信息") L.append(f"- 姓名:{name}") L.append(f"- 性别:{gender}") L.append(f"- 出生日期:{birth or '(未提供)'}") L.append(f"- 当前年龄:{age_disp}") L.append(f"- 建档日期:{today}") ``` ```python L.append("## 六、既往史 / 过敏 / 注意事项") L.append(f"- 过敏史:{child.get('allergy') or '无记录'}") L.append(f"- 既往疾病:{child.get('illness') or '无记录'}") L.append(f"- 其他备注:{child.get('notes') or (query if query else '无')}") ``` The complete generated content is then retained in a global dictionary: ```python with _lock: _orders[out_trade_no] = {"paid": False, "content": execute_business(data)} ``` ### Technical Analysis The global `_orders` dictionary has no time-to-live, cleanup process, maximum capacity, or deletion after successful delivery. It retains the generated Markdown record until the process terminates. Although the original JSON object is not directly inserted into `_orders`, the generated record reproduces substantial sensitive input, including a child's name, sex, birth date, growth measurements, vaccine history, allergies, illnesses, and free-form notes. It therefore remains sensitive pediatric health information. The documented privacy statement says original information is temporarily cached only during the payment session and cleared when the session ends. The implementation provides no session-ending cleanup and does not define a bounded retention period for generated content. ### Attack Path 1. Users submit pediatric health information to create records. 2. Before payment completes, `execute_business(data)` creates a record containing the ...[truncated 934 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
mch-demo/server.py:637
Finding

Unbounded Request Body Reading Enables Remote Resource Exhaustion

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

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

Production Dependencies Are Unpinned and Lack Integrity Verification

Content
View full analysis
=2.31 cryptography>=42.0 ``` The Docker build installs whichever versions currently satisfy these ranges: ```dockerfile # 先装依赖(利用 Docker 层缓存) COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt ``` ### Technical Analysis Both dependencies use open-ended lower bounds. A rebuild can therefore install any future version satisfying the range, including versions that have not been reviewed or tested with this project. The dependency file also contains no package hashes. Package integrity consequently depends entirely on the package index and transport trust at build time. The audit found no typosquatted package names or explicitly malicious package sources; the risk arises from broad, mutable resolution and lack of reproducibility. This concern is particularly relevant because `cryptography` processes private keys, signatures, certificates, and encrypted payment callbacks, while `requests` handles outbound payment-network communication. ### Attack Path 1. The image is rebuilt at a later date. 2. The package resolver selects newer dependency or transitive-dependency versions allowed by the open-ended constraints. 3. A compromised, malicious, incompatible, or behaviorally changed release is downloaded. 4. The release executes during installation or is imported by `server.py` at runtime. 5. Depending on the affected package, it could access application data, environment variables, mounted private keys, or payment traffic. This is a supply-chain hardening weakness rather than evidence that the currently named packages are malicious. ### Impact Assessment Potential impact depends on the behavior of a future dependency release. Because the container receives merchan ...[truncated 365 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (46)

Tainted flow: 'path' from os.environ.get (line 184, 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/server.py (reported line 171)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 184, 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/server.py (reported line 189)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 184, 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/server.py (reported line 223)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 219, 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/server.py (reported line 326)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()
    # 优先取接口返回的 payment_code;否则用本机生成的 L1 信封

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose says data is submitted to mch.1001058.xyz for one-time record generation, but the behavior described/observed includes broader payment orchestration, third-party payment communications, callback handling, and transient state retention that are not fully disclosed. This is dangerous because users and agents may consent to a narrow pediatric-record service while the skill actually triggers additional processing paths involving child health data, payments, and extra external systems, creating material privacy, transparency, and compliance risk.

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

md
# 复制服务代码
COPY server.py .

# 不把 .env 打进镜像;运行时通过挂载或环境变量注入
# 如需默认值,可改为 COPY .env.example .env.example

EXPOSE 8080

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

dockerfile
# 复制服务代码
COPY server.py .

# 不把 .env 打进镜像;运行时通过挂载或环境变量注入
# 如需默认值,可改为 COPY .env.example .env.example

EXPOSE 8080

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

yaml
# 复制服务代码
COPY server.py .

# 不把 .env 打进镜像;运行时通过挂载或环境变量注入
# 如需默认值,可改为 COPY .env.example .env.example

EXPOSE 8080

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/server.py (reported line 14)May include surrounding context.

python
# 复制服务代码
COPY server.py .

# 不把 .env 打进镜像;运行时通过挂载或环境变量注入
# 如需默认值,可改为 COPY .env.example .env.example

EXPOSE 8080

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/server.py (reported line 120)May include surrounding context.

python
# 复制服务代码
COPY server.py .

# 不把 .env 打进镜像;运行时通过挂载或环境变量注入
# 如需默认值,可改为 COPY .env.example .env.example

EXPOSE 8080

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

md
# 复制服务代码
COPY server.py .

# 不把 .env 打进镜像;运行时通过挂载或环境变量注入
# 如需默认值,可改为 COPY .env.example .env.example

EXPOSE 8080

Credential Access

High
Category
Privilege Escalation
Confidence
87% confidence
Finding

Loading a local .env file into the container commonly injects secrets such as API keys, payment credentials, or private configuration at runtime. In a skill handling pediatric health records and payment-related materials, this increases the sensitivity of any accidental exposure through image leakage, misconfigured logging, debugging endpoints, or compromised container access.

Content

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

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

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

This compose file mounts a WeChat Pay private key from the host into the container, exposing a highly sensitive signing credential to the application runtime. If the container is compromised, an attacker could steal the key and impersonate the merchant or sign fraudulent payment-related requests, and the hardcoded host path also reveals local filesystem details.

Content

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

yaml
ports:
      - "8080: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
96% confidence
Finding

The SkillHub developer private key is mounted into the application container, making a private signing or authentication credential available to any process that gains access inside the container. Because this service processes sensitive child health data, theft of this key could enable unauthorized requests, impersonation, or abuse of trusted integrations around the skill.

Content

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

python
from cryptography.x509 import load_pem_x509_certificate


def _load_dotenv(path=".env"):
    """健壮加载 .env,支持无引号多行 PEM 私钥(如 SkillHub 私钥)。
    原生 python-dotenv 对无引号多行值解析失败,这里手动处理:
    遇到 KEY= 且值以 -----BEGIN 开头、不含 -----END 时进入多行收集,

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/server.py (reported line 84)May include surrounding context.

python
from cryptography.x509 import load_pem_x509_certificate


def _load_dotenv(path=".env"):
    """健壮加载 .env,支持无引号多行 PEM 私钥(如 SkillHub 私钥)。
    原生 python-dotenv 对无引号多行值解析失败,这里手动处理:
    遇到 KEY= 且值以 -----BEGIN 开头、不含 -----END 时进入多行收集,

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

The deployment flow relies on editing a plaintext .env file on the NAS to supply operational configuration tied to payment processing, in a project that also stores merchant secrets. In practice this encourages secret handling through files that may be exposed via weak permissions, backups, shell history, or accidental sharing, creating a realistic path to credential theft and fraudulent payment operations.

Content

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

  • 外部 443 → NAS 的 LAN IP 443
  • 外部 80 → NAS 的 LAN IP 80(仅 Let's Encrypt HTTP-01 验证时需要,验证完可关,但建议常开以免证书续期失败)

步骤 6:改 .env 并重启容器

在 NAS 上把 mch-demo/.env 里的占位改成真实公网地址,然后重启容器(Container Manager → 项目 → 重新部署 / 容器 → 重启):

text
PAY_NOTIFY_URL=https://<你的域名>/api/pay/notify

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

This section states that apiclient_key.pem is mounted into the container and that paths align with values in .env, confirming that sensitive merchant key material is deployed as filesystem artifacts on the NAS/container stack. Private key exposure would let an attacker impersonate the merchant to payment APIs or abuse callback-related trust, which is especially serious for a public-facing payment service tied to pediatric health data workflows.

Content

Scanner excerpt · mch-demo/部署-群晖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`)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares network- and environment-dependent behavior but omits any explicit tool/permission scope, which weakens platform-level consent and policy enforcement. In this context the skill handles highly sensitive children's health data and payment-related flows, so undeclared capabilities increase the risk of unauthorized exfiltration, accidental overreach, or unsafe execution by an agent runtime.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The skill’s natural-language instructions and user-facing example copy are entirely in Chinese, and the document does not indicate that users 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 restriction is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill loads a broad set of payment, certificate, and private-key materials from environment variables, which exceeds the minimum capability implied by a pediatric-record organization skill. In a health-data context, unnecessary secret-handling capability raises the consequences of compromise and broadens the blast radius if the service is abused or misconfigured.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The implementation behaves as a generic WeChat/SkillHub payment merchant demo rather than a narrowly scoped pediatric-record submission service tied to the manifest-declared merchant endpoint mch.1001058.xyz. This scope mismatch increases the attack surface and makes it easier to process payments, callbacks, and related data flows beyond what users would reasonably expect from the stated health-record service.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.