Back to skill

Security audit

Ha Xiaomi Control

Security checks for vulnerabilities and agentic risk

Overview

This skill appears intended for Home Assistant Xiaomi control, but it exposes broad authenticated smart-home control with weak scoping and an insecure HTTP default.

Install only if you intend to let an agent control your Home Assistant devices. Use a dedicated least-privileged token, prefer HTTPS even on local networks, restrict the skill to known entities/actions, and require confirmation before speaker, HVAC, lock, alarm, or other physical-device commands.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ha_control.py:23
Finding

Unrestricted Authenticated Home Assistant Service Invocation

Content
View full analysis

Vulnerability Details

File Location: scripts/ha_control.py, lines 23-34 and 67-70
Vulnerability Type: Missing allowlist and insufficient input validation
Risk Level: High

Vulnerable Code

python
def call_service(entity_id, service, data=None):
    """Call Home Assistant service"""
    url = f"{HA_URL}/api/services/{service}"
    
    headers = {
        "Authorization": f"Bearer {HA_TOKEN}",
        "Content-Type": "application/json"
    }
    
    payload = {"entity_id": entity_id}
    if data:
        payload.update(data)
python
entity_id = sys.argv[1]
service = sys.argv[2]
data = json.loads(sys.argv[3]) if len(sys.argv) > 3 else None

success = call_service(entity_id, service, data)

Technical Analysis

The script accepts the Home Assistant service path, entity identifier, and arbitrary JSON fields directly from command-line arguments. It performs no allowlist validation for permitted services or entities and does not validate the schema, type, range, or names of additional payload fields.

Although the Skill is documented as a controller for specific Xiaomi speakers and air conditioners, the implementation can invoke any Home Assistant service accessible to the configured bearer token. The supplied service value is interpolated directly into the API endpoint, while caller-controlled JSON is merged into the authenticated request body.

This is not operating-system command injection, because the values are not passed to a shell. The security issue is excessive API authority: the generic authenticated service-call primitive exposes substantially more functionality than the Skill's declared purpose.

Attack Path

  1. An attacker or untrusted caller gains the ability to invoke ha_control.py.
  2. The caller supplies an entity outside the documented Xiaomi device list.
  3. The caller supplies a Home Assistant service associated with that entity or another privileged integration.
  4. The caller optionally prov ...[truncated 1144 chars]
Remediation
View remediation

Remediation Suggestions

  1. Define an explicit allowlist of permitted entity and service combinations. For example, only allow the documented Xiaomi entity IDs with their required services.
  2. Reject any entity or service that is not present in the allowlist.
  3. Define a strict payload schema for each operation:
    • Require text values to be strings with a reasonable maximum length.
    • Restrict air-conditioner temperatures to the documented range of 16–30°C.
    • Restrict mode options to Auto, Cool, Heat, Dry, or Fan.
    • Reject unknown payload fields.
  4. Do not expose a generic service path to callers. Map high-level actions such as turn_ac_off to fixed internal service and entity values.
  5. Use a dedicated, least-privileged Home Assistant account or token whose permissions are limited to the required entities.
  6. Log security-relevant validation failures without logging the bearer token or sensitive command content.
  7. Require explicit user confirmation for safety-sensitive physical actions where appropriate.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ha_control.py:20
Finding

Home Assistant Bearer Token Transmitted over Plaintext HTTP by Default

Content
View full analysis

Vulnerability Details

File Location: scripts/ha_control.py, lines 20-29; SKILL.md, lines 11-16
Vulnerability Type: Plaintext transmission of an authentication credential
Risk Level: High

Vulnerable Code

python
# Configuration
HA_URL = os.environ.get("HA_URL", "http://192.168.31.35:8123")
HA_TOKEN = os.environ.get("HA_TOKEN", "")

def call_service(entity_id, service, data=None):
    """Call Home Assistant service"""
    url = f"{HA_URL}/api/services/{service}"
    
    headers = {
        "Authorization": f"Bearer {HA_TOKEN}",
        "Content-Type": "application/json"
    }

The insecure default is also documented in SKILL.md:

markdown
## Configuration

Load configuration from `TOOLS.md` → **智能家居** section, or use these defaults:

- **HA URL:** `http://192.168.31.35:8123`
- **Access Token:** Read from user's environment or TOOLS.md
- **Xiao AI Speaker:** `media_player.xiaomi_lx06_3ff3_play_control`
- **Xiao AI Command Entity:** `text.xiaomi_lx06_3ff3_execute_text_directive`
- **Air Conditioner:** `button.miir_ir02_8112_turn_off` / `button.miir_ir02_8112_turn_on`

Technical Analysis

The default Home Assistant endpoint uses unencrypted HTTP, while every request carries the bearer token in the Authorization header. HTTP provides neither confidentiality nor transport integrity.

Consequently, the long-lived credential and request body may be exposed to an attacker capable of observing local-network traffic. A network-positioned attacker may also modify requests or responses through a man-in-the-middle attack. The documentation only recommends HTTPS for remote access, but local networks should not be assumed trustworthy.

The implementation does not reject an HTTP URL, warn before sending credentials over plaintext transport, or restrict insecure HTTP to a loopback address.

Attack Path

  1. The operator uses the default HA_URL or configures another http:// endpoint.
  2. The script sends a Home Assist ...[truncated 1170 chars]
Remediation
View remediation

Remediation Suggestions

  1. Change the default endpoint to an HTTPS URL and require TLS for all non-loopback connections.
  2. Validate HA_URL before constructing a request and reject plaintext HTTP unless the destination is explicitly limited to a trusted loopback development environment.
  3. Configure Home Assistant with TLS directly or place it behind a properly configured HTTPS reverse proxy.
  4. Retain standard certificate and hostname verification; do not disable TLS verification to work around certificate errors.
  5. Use a private certificate authority trusted by the host when public certificates are unsuitable for the local network.
  6. Issue a dedicated least-privileged token for this Skill and rotate any token previously transmitted over an untrusted plaintext network.
  7. Fail before making a request when HA_TOKEN is empty, and provide an error message that does not disclose credential content.
  8. Update SKILL.md to require HTTPS for both local and remote access rather than treating local plaintext transport as the default.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (10)

Tainted flow: 'req' from os.environ.get (line 37, credential/environment) → urllib.request.urlopen (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 · scripts/ha_control.py (reported line 45)May include surrounding context.

python
)
    
    try:
        with urllib.request.urlopen(req) as response:
            result = response.read().decode('utf-8')
            print(f"✅ Success: {service} called on {entity_id}")
            if result:

Credential Access

High
Category
Privilege Escalation
Confidence
87% confidence
Finding

The skill instructs loading an access token from the environment or TOOLS.md, and TOOLS.md may be a less secure or more broadly readable location than a dedicated secret store. Combining token access with network capabilities creates a realistic path for misuse of Home Assistant credentials if the skill or surrounding tooling is compromised.

Content

Scanner excerpt · SKILL.md (reported line 15)May include surrounding context.

md
Load configuration from `TOOLS.md` → **智能家居** section, or use these defaults:

- **HA URL:** `http://192.168.31.35:8123`
- **Access Token:** Read from user's environment or TOOLS.md
- **Xiao AI Speaker:** `media_player.xiaomi_lx06_3ff3_play_control`
- **Xiao AI Command Entity:** `text.xiaomi_lx06_3ff3_execute_text_directive`
- **Air Conditioner:** `button.miir_ir02_8112_turn_off` / `button.miir_ir02_8112_turn_on`

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

md
## Security Notes

- ⚠️ Access Token is sensitive - never log or expose it
- ✅ Store token in environment variable or secure config
- ✅ Use HTTPS for remote HA access

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill uses sensitive capabilities (reading environment configuration and making network requests) but does not declare any explicit tool scope or permission boundaries. This increases the chance of over-privileged execution and makes it harder for a runtime or reviewer to constrain what the skill is allowed to access.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The description says the skill triggers on generic 'device control commands,' which is broad enough to invoke the skill unexpectedly from normal conversation. Because the skill performs real-world actions against home devices, accidental activation can lead to unauthorized or unintended device control.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 37)May include surrounding context.

API Call:

bash
curl -X POST \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"entity_id": "text.xiaomi_lx06_3ff3_execute_text_directive", "value": "${COMMAND}"}' \

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Triggering air-conditioner control whenever the message contains the single keyword '空调' is ambiguous and can match informational or incidental mentions. In a home-automation context, this raises the risk of unintended physical actions such as changing temperature or powering devices on/off without clear user intent.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 58)May include surrounding context.

Example - Turn Off:

bash
curl -X POST \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"entity_id": "button.miir_ir02_8112_turn_off"}' \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This reference enumerates callable Home Assistant services for physical device control, including speakers and HVAC, without any warning that invoking them causes real-world actions or may disclose private speech/content through text-to-speaker features. In the context of an agent skill designed to trigger on device-control commands, omission of safety guidance increases the risk of unintended actuation, socially disruptive behavior, and privacy-impacting output.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The reference uses Chinese-language function names and device descriptions such as '执行文本指令', '播放文本', and '关闭空调' without indicating that the skill is intentionally Chinese-only or offering an alternative language. Under SQP-3, forcing a specific language or locale without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.