Back to skill

Security audit

xiaoai-ha-control

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent smart-speaker/Home Assistant purpose, but its optional bridge exposes an unauthenticated network path into the main OpenClaw agent and stores recent voice text in local/status files.

Install only if you are comfortable running a local smart-home bridge that can control XiaoAI/Home Assistant and invoke your main OpenClaw agent. Before enabling the bridge, bind it to localhost or a trusted interface, add authentication, do not expose port 8765 publicly, restrict the agent/tools used for bridge requests, protect `.env` and log/status files, and assume voice transcripts may contain private household data.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
bridge_server.py:151
Finding

Unauthenticated Network Endpoint Can Invoke the Main Agent

Content
View full analysis
tuple[bool, str, str]: normalized = normalize_text(text) if not normalized: return False, 'empty_text', '' matched_subagent = detect_named_subagent(text) if source != 'xiaoai-speaker': return True, 'non_xiaoai_source', matched_subagent has_target = any(target in normalized for target in BRIDGE_WHITELIST_TARGETS) has_verb = any(verb in normalized for verb in BRIDGE_WHITELIST_VERBS) direct_target = any(normalized.startswith(target) for target in BRIDGE_WHITELIST_TARGETS) if has_target and (has_verb or direct_target): return True, 'matched_bridge_whitelist', matched_subagent return False, 'not_in_bridge_whitelist', matched_subagent ``` ```python length = int(self.headers.get('Content-Length', '0')) body = self.rfile.read(length) if length > 0 else b'{}' payload = json.loads(body.decode('utf-8') or '{}') text = str(payload.get('text', '')).strip() source = str(payload.get('source', 'xiaoai-speaker')).strip() or 'xiaoai-speaker' ``` ```python server = HTTPServer((HOST, PORT), Handler) server.serve_forever() ``` ### Technical Analysis The bridge listens on every network interface through `0.0.0.0` but does not require a bearer token, HMAC signature, client certificate, or other authentication. Consequently, any client that can reach TCP port 8765 can submit text to the bridge. The `source` value is also entirely client-controlled. The forwarding function automatically approves every nonempty request where `source` is not exactly `xiaoai-speaker`. This allows a remote client to bypass the XiaoAI whitel ...[truncated 1939 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
bridge_server.py:188
Finding

Untrusted Voice and HTTP Text Is Embedded Directly into Main-Agent Instructions

Content
View full analysis
str: subagent_hint = '' if matched_subagent: subagent_hint = ( f'命中目标子 agent:{matched_subagent}。' '若该消息带小爱来源标识且文本中明确点名了该子 agent,main 必须将任务分配给对应子 agent;' '子 agent 完成后结果必须先回到 main,再由 main 统一负责聊天回复与小爱口播。' ) return ( f"【来自小爱语音】\n消息来源:{source}\n用户原话:{text}\n\n" '这是来自小爱音箱/语音桥的上行请求。' '请优先按“来源是小爱”的语义来理解,而不是按普通聊天消息理解。' '如果原话中出现“告诉小爱同学”“让小爱”这类说法,先判断是否只是口语包壳或自指表达,必要时做语义纠偏后再处理。' + subagent_hint + '请按 AGENTS.md 中的小爱语音桥处理规则执行:' '由管家统一调度,必要时分配给子 agent;' '聊天窗口保留完整结果;' '若需要语音回播,请按 AGENTS.md 中的长期规则执行。' '不要输出 markdown,不要分点,不要带多余解释。' ) def run_openclaw(prompt: str) -> tuple[str, str, int]: proc = subprocess.run( [OPENCLAW_BIN, 'agent', '--agent', 'main', '--message', prompt], capture_output=True, text=True, timeout=OPENCLAW_TIMEOUT, ) return (proc.stdout or '').strip(), (proc.stderr or '').strip(), proc.returncode ``` ```python stdout, stderr, returncode = run_openclaw( build_prompt(text, source, matched_subagent) ) ``` ### Technical Analysis The bridge interpolates untrusted voice or HTTP content directly into a prompt that is sent to the privileged `main` agent. Although the subprocess call uses an argument list and is not vulnerable to conventional shell metacharacter injection, the semantic boundary between trusted bridge instructions and attacker-controlled content is weak. The content is labeled as the user's original speech, but the prompt does not clearly direct the agent to treat instructions inside that field strictly as untrusted data. An attacker can therefore include text th ...[truncated 1495 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
bridge_server.py:318
Finding

Conversation Data Is Exposed and Persisted with Unsafe Daemon Permissions

Content
View full analysis
None: for path in [LAST_FILE, REPLY_FILE, ERROR_FILE, RAW_FILE, STATUS_FILE, REQUEST_LOG]: if not path.exists(): path.write_text('' if path != STATUS_FILE else '{}', encoding='utf-8') def append_log(line: str) -> None: REQUEST_LOG.open('a', encoding='utf-8').write(line + '\n') ``` ```python def do_GET(self) -> None: if self.path == '/health': status = read_json(STATUS_FILE) if not status: status = { 'service': 'xiaoai-ha-control-bridge', 'healthy': True, 'updated_at': now_str(), } self._send(200, {'ok': True, 'status': status}) return self._send(404, {'ok': False, 'error': 'not_found'}) ``` ```python append_log(f'[{request_at}] RECEIVED source={source!r} text={text!r}') RAW_FILE.write_text(text, encoding='utf-8') LAST_FILE.write_text(text, encoding='utf-8') ``` ```python os.chdir('/') os.setsid() os.umask(0) ``` ### Technical Analysis The service writes raw voice text, the most recent message, replies, errors, status, and request logs to files under the Skill directory. It does not redact sensitive content, rotate logs, enforce retention, or explicitly set restrictive file modes. In daemon mode, the process sets `umask(0)`. Files subsequently created with norma ...[truncated 1704 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/xiaoai_say.sh:5
Finding

Credential Configuration File Is Executed as Shell Code

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (36)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · README.md (reported line 82)May include surrounding context.

md
2. 已安装 **HACS**
3. 已安装 **Xiaomi Miot** 集成
4. 已将 **小爱音箱** 接入 Home Assistant
5. 已创建 **Home Assistant Long-Lived Access Token**
6. 已找到以下实体:
   - `play_text` 文本播报实体
   - `execute_text_directive` 文本指令实体

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · README.md (reported line 192)May include surrounding context.

md
2. 已安装 **HACS**
3. 已安装 **Xiaomi Miot** 集成
4. 已将 **小爱音箱** 接入 Home Assistant
5. 已创建 **Home Assistant Long-Lived Access Token**
6. 已找到以下实体:
   - `play_text` 文本播报实体
   - `execute_text_directive` 文本指令实体

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 169)May include surrounding context.

复制模板:

bash
cp ~/.openclaw/skills/xiaoai-ha-control/.env.example ~/.openclaw/skills/xiaoai-ha-control/.env

编辑 .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 · scripts/xiaoai_execute.sh (reported line 5)May include surrounding context.

sh
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ENV_FILE="${SCRIPT_DIR}/../.env"

if [ -f "$ENV_FILE" ]; then
  # shellcheck disable=SC1090

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 · scripts/xiaoai_play.sh (reported line 5)May include surrounding context.

sh
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ENV_FILE="${SCRIPT_DIR}/../.env"

if [ -f "$ENV_FILE" ]; then
  # shellcheck disable=SC1090

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 · scripts/xiaoai_say.sh (reported line 5)May include surrounding context.

sh
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ENV_FILE="${SCRIPT_DIR}/../.env"

if [ -f "$ENV_FILE" ]; then
  # shellcheck disable=SC1090

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README documents capturing Xiaomi voice text via a Home Assistant conversation sensor and forwarding it to a bridge service, but it does not give an explicit privacy warning about collecting, relaying, logging, or retaining potentially sensitive spoken content. Because the skill also mentions request logging and upstream forwarding to OpenClaw, users may unknowingly expose personal or household data beyond the voice assistant’s native processing boundary.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 157)May include surrounding context.

例如:

bash
mkdir -p ~/.openclaw/skills/xiaoai-ha-control
cp -R xiaoai-ha-control/* ~/.openclaw/skills/xiaoai-ha-control/
chmod +x ~/.openclaw/skills/xiaoai-ha-control/scripts/*.sh

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 157)May include surrounding context.

例如:

bash
mkdir -p ~/.openclaw/skills/xiaoai-ha-control
cp -R xiaoai-ha-control/* ~/.openclaw/skills/xiaoai-ha-control/
chmod +x ~/.openclaw/skills/xiaoai-ha-control/scripts/*.sh

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README states the bridge listens on 0.0.0.0:8765, which exposes the service on all network interfaces, but it does not include a clear security warning or restriction guidance. If the bridge lacks strong authentication or request validation, any reachable host on the LAN—or beyond, if port forwarding/firewall rules permit—could submit requests, inject commands, or harvest status/voice data.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 369)May include surrounding context.

md
在 Mac 上使用 launchd 或 Linux 上使用 systemd,可以让服务开机自启:

- Mac(launchd):将 `scripts/com.shinechen.xiaoai-bridge.plist` 复制到 `~/Library/LaunchAgents/`,然后 `launchctl load`(仅供参考,请根据实际情况修改 Label 和路径)
- Linux(systemd):创建对应的 service unit

### launchd 注意事项(重要)

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 376)May include surrounding context.

md
在 Mac 上使用 launchd 或 Linux 上使用 systemd,可以让服务开机自启:

- Mac(launchd):将 `scripts/com.shinechen.xiaoai-bridge.plist` 复制到 `~/Library/LaunchAgents/`,然后 `launchctl load`(仅供参考,请根据实际情况修改 Label 和路径)
- Linux(systemd):创建对应的 service unit

### launchd 注意事项(重要)

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 369)May include surrounding context.

md
在 Mac 上使用 launchd 或 Linux 上使用 systemd,可以让服务开机自启:

- Mac(launchd):将 `scripts/com.shinechen.xiaoai-bridge.plist` 复制到 `~/Library/LaunchAgents/`,然后 `launchctl load`(仅供参考,请根据实际情况修改 Label 和路径)
- Linux(systemd):创建对应的 service unit

### launchd 注意事项(重要)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This markdown file states that the skill can make the XiaoAI device speak text, execute text commands, and play URL audio, but it does not warn that these actions may trigger real-world device behaviors or unintended operations. For markdown files, omission of warnings about behaviors affecting user environment or system-integrated devices qualifies as a missing user warning.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill describes shell execution, environment variable use, file interactions, and networked control of Home Assistant/Xiaomi devices, but it does not declare any explicit tool scope or permission boundaries. This creates an authorization ambiguity where an orchestrator may allow broader-than-necessary capabilities, increasing the risk of unintended command execution or access to sensitive configuration such as HA tokens.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The documentation advertises the ability to execute commands via XiaoAI, play remote audio URLs, and bridge upstream voice text into OpenClaw, but it does not clearly warn users about the security implications of device control, outbound network access, and trust boundaries in the bridge path. In this context, missing warnings and safeguards increase the chance that operators enable powerful behavior without understanding that remote content, home automation actions, or relayed voice inputs may have security consequences.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger rule treats any normal message containing “小爱/小爱同学” as a reason to invoke device-control behavior, which is overly broad for a conversational environment. This can cause accidental routing of benign chat into exec, say, or play, potentially leading to unintended speaker actions, command execution through XiaoAI, or playback of attacker-supplied content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The document describes a voice-triggered bridge that can forward XiaoAI speech into OpenClaw and perform downstream actions such as speaking, executing, and playing content, but it does not prominently warn users about the security consequences of voice-originated command routing and device control. In this skill context, that omission matters because users may deploy the bridge without understanding risks like unintended command execution, unauthorized device actions, or abuse via weak whitelist rules.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The forwarding logic explicitly allows all non-xiaoai-speaker sources to be forwarded to OpenClaw, which broadens the trust boundary beyond the skill's stated XiaoAI bridge purpose. Because the server binds to 0.0.0.0 and does not authenticate requests, any reachable client can potentially submit arbitrary text for agent execution through this path.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest frames the skill around controlling XiaoAI via Home Assistant/Xiaomi Miot and optionally bridging XiaoAI voice to OpenClaw. In this file, the core worker invokes an external 'openclaw agent --agent main' subprocess to process forwarded content, which is a broader agent-execution capability than simple device control and is only partially justified when the incoming request is not clearly limited to documented XiaoAI-origin traffic.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

User-provided voice text is forwarded to an external agent subprocess, which expands the data exposure surface beyond the local HTTP handler. In this skill context, messages may contain home-control intents, personal reminders, or other sensitive content, so undisclosed forwarding increases privacy and misuse risk even if the subprocess is local.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · bridge_server.py (reported line 212)May include surrounding context.

python
def run_openclaw(prompt: str) -> tuple[str, str, int]:
    proc = subprocess.run(
        [OPENCLAW_BIN, 'agent', '--agent', 'main', '--message', prompt],
        capture_output=True,
        text=True,

Tainted flow: 'OPENCLAW_BIN' from os.environ.get (line 22, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
95% confidence
Finding

The executable path comes from the OPENCLAW_BIN environment variable and is then launched as a subprocess without validation. If an attacker can influence the service environment, they can replace the intended binary with an arbitrary program and gain code execution in the bridge process context.

Content

Scanner excerpt · bridge_server.py (reported line 212)May include surrounding context.

python
def run_openclaw(prompt: str) -> tuple[str, str, int]:
    proc = subprocess.run(
        [OPENCLAW_BIN, 'agent', '--agent', 'main', '--message', prompt],
        capture_output=True,
        text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · bridge_server.py (reported line 223)May include surrounding context.

python
def speak_reply(spoken: str) -> tuple[str, int]:
    proc = subprocess.run(
        ['bash', XIAOAI_BIN, 'say', spoken],
        capture_output=True,
        text=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Incoming request text is persistently written to local files and logs, which may capture sensitive voice content, commands, or personal data without any minimization or access control shown in the code. If the host is shared, backed up broadly, or later compromised, these files create an avoidable privacy and data-exposure risk.

Content

No source excerpt is available for this finding.