T09 · Insecure Skill Coding Practices
- Location
scripts/setup.py:153- Finding
Gateway Bearer Token Provisioned for Plaintext HTTP Connections
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill’s Apple Health syncing purpose is coherent, but it under-discloses high-impact handling of gateway tokens, network exposure, and persistent health data.
Review this before installing if the OpenClaw gateway is reachable beyond your own machine or trusted LAN. Do not share setup QR codes, raw JSON, screenshots, or terminal logs, because they can contain a live gateway token. Prefer HTTPS, VPN, or a trusted tunnel for any remote/VPS use, avoid opening port 18789 broadly, install dependencies yourself in an isolated environment, and restrict permissions on ~/.apple-health-sync because it stores sensitive health data.
scripts/setup.py:153Gateway Bearer Token Provisioned for Plaintext HTTP Connections
scripts/setup.py:198Complete Gateway Bearer Token Disclosed Through QR Code and Terminal Output
scripts/setup.py:121Automatic Installation of an Unpinned Package from the Active Pip Index
scripts/ingest.py:227Owner-Only Permissions Are Not Enforced for the Sensitive Health Database
A second description-behavior mismatch is present: the skill markets itself as an end-to-end Apple Health sync mechanism, yet the visible commands only read provided input and local state. Such overclaiming can mislead operators into exposing services or trusting data-handling paths that are not transparently implemented.
A second description-behavior mismatch is present: the skill markets itself as an end-to-end Apple Health sync mechanism, yet the visible commands only read provided input and local state. Such overclaiming can mislead operators into exposing services or trusting data-handling paths that are not transparently implemented.
The setup flow states that it reads a gateway bearer token automatically and emits a QR code or raw JSON for manual entry, but it does not require or prominently present a warning that these materials contain connectivity and authentication details. If the QR code, terminal output, screenshots, logs, or copied JSON are exposed, an attacker could gain unauthorized access to the gateway or associated health-data channel.
The skill invokes Python scripts for setup, ingest, and query, and those workflows imply shell execution, file/database access, and network exposure, but the manifest does not declare any tool restrictions or permissions. This weakens reviewability and containment because a host may grant broader capabilities than users or operators expect.
The skill instructs users to open TCP port 18789 and even provides firewall commands, but it does not explain the security implications of exposing a service to the LAN or internet. In context, this could expose a health-data ingestion or gateway endpoint to unauthorized probing, abuse, or token theft if access controls are weak.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# Linux iptables
sudo iptables -A INPUT -p tcp --dport 18789 -j ACCEPT
# Ubuntu ufw
sudo ufw allow 18789/tcp
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# Linux iptables
sudo iptables -A INPUT -p tcp --dport 18789 -j ACCEPT
# Ubuntu ufw
sudo ufw allow 18789/tcp
The trigger for health queries is broad enough to activate on ordinary health-related conversation, potentially causing the agent to access or summarize sensitive biometric data without sufficiently clear user intent. In a health-data skill, overbroad activation increases privacy risk because the underlying data is highly sensitive even if the action is read-only.
The instruction to format query output naturally in Chinese imposes a fixed language requirement. The file does not offer a user opt-in or explain a justified region-specific constraint, so this conflicts with the language-choice policy.
The rule to auto-ingest incoming health data without confirmation enables autonomous processing of highly sensitive biometric information. In this context, even if triggered by a recognizable prefix, skipping confirmation increases the chance of ingesting spoofed, misrouted, or unintended data and storing it persistently without informed user approval.
## Rules
1. Auto-ingest first, acknowledge second — no confirmation prompts on incoming data.
2. Never fabricate data — only report what's in the database.
3. All responses in Chinese.
4. Never expose the bearer token to the user.
This rule explicitly requires every response to be in Chinese. Because no language preference choice or justified locale limitation is provided, it constitutes a natural-language policy violation.
The parsing logic only accepts messages containing a Chinese header variant and then extracts fields using Chinese labels like "类型:" and "时间:". This effectively hard-codes a specific language/locale behavior without user opt-in or an explicitly documented regional constraint.
The script hardcodes Chinese period labels and later emits Chinese-language messages and metric names, which imposes a specific language on all users. There is no opt-in, locale selection, or documented justification that this skill is intended only for Chinese-speaking or region-specific use.
Multiple user-facing strings throughout the script are hard-coded in Chinese, including errors, warnings, status messages, and CLI help text. This enforces a specific language for all users without opt-in or justification, which matches the language/locale policy-violation category.
The script launches or restarts the external OpenClaw gateway automatically, which changes system and network state as a side effect of generating a pairing QR code. Because the QR payload includes the gateway URL and token, automatically exposing or restarting a network service can increase the chance of unintended remote accessibility, especially on VPS hosts.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"""Start/restart gateway in the specified bind mode."""
print(f"→ 启动 OpenClaw gateway(bind={bind_mode})...", flush=True)
try:
subprocess.Popen(
["openclaw", "gateway", "--bind", bind_mode, "--force"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
# Try qrencode (brew/apt install qrencode)
for mode in (["ansiutf8"] if not compact else ["ansi"]):
try:
result = subprocess.run(
["qrencode", "-t", mode, "-m", "1", data],
capture_output=True, text=True
)
A setup script that silently installs packages via pip performs privileged environment modification and can pull executable code from external repositories during a routine pairing flow. In the context of a security-sensitive tool that reads a gateway token and prepares network access, this makes the behavior more dangerous because users may run it on trusted hosts expecting only local configuration output.
The setup script automatically installs a Python package at runtime via pip, which introduces unreviewed code into the environment and creates package-management side effects beyond simple QR setup. This expands the supply-chain attack surface and can execute arbitrary install-time code from dependency packages if the package source or dependency resolution is compromised.
# Auto-install and retry
print("→ 正在安装 qrcode 库...", flush=True)
try:
subprocess.run(
[sys.executable, "-m", "pip", "install", "qrcode", "-q"],
check=True, capture_output=True
)
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
def firewall_hint(ip: str, port: int):
print(f"\n⚠️ VPS 防火墙配置(如果手机无法连接):")
print(f" Linux iptables: sudo iptables -A INPUT -p tcp --dport {port} -j ACCEPT")
print(f" Ubuntu ufw: sudo ufw allow {port}/tcp")
print(f" Oracle Cloud: 控制台 → VCN → Security List → 添加入站规则 TCP {port}")
print(f" 确认后可用以下命令测试连通性(在另一台机器上):")
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
def firewall_hint(ip: str, port: int):
print(f"\n⚠️ VPS 防火墙配置(如果手机无法连接):")
print(f" Linux iptables: sudo iptables -A INPUT -p tcp --dport {port} -j ACCEPT")
print(f" Ubuntu ufw: sudo ufw allow {port}/tcp")
print(f" Oracle Cloud: 控制台 → VCN → Security List → 添加入站规则 TCP {port}")
print(f" 确认后可用以下命令测试连通性(在另一台机器上):")
No suspicious patterns detected.