Back to skill

Security audit

Home Assistant Integration

Security checks for vulnerabilities and agentic risk

Overview

This Home Assistant skill is a disclosed smart-home control integration with real privacy and physical-device risks, but its sensitive behavior is purpose-aligned and includes meaningful user controls.

Install only for a Home Assistant instance you own. Use a dedicated low-privilege Home Assistant user, prefer HTTPS, keep HOME_ASSISTANT_ALLOW_HTTP unset unless you knowingly accept LAN cleartext token risk, keep HOME_ASSISTANT_ALLOW_LOCKS unset unless you truly want lock/alarm control, and restrict who can message any OpenClaw channel connected to this skill because read-only home status can reveal occupancy and device information.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

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

md
- name: HOME_ASSISTANT_URL
      description: Your Home Assistant URL (e.g. http://homeassistant.local:8123)
    - name: HOME_ASSISTANT_TOKEN
      description: Long-lived access token (HA Profile > Security > Long-Lived Access Tokens)
  optional_env:
    - name: HOME_ASSISTANT_CA_CERT
      description: Path to a CA certificate file so HTTPS with a self-signed cert is verified (the supported way to use a self-signed cert).

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

md
"description": "Home Assistant REST API integration for OpenClaw agents. Query and control your smart home via natural language through Telegram or any OpenClaw channel. Covers: lights, switches, climate/heating, temperature sensors, cameras, automations, energy monitoring, EV chargers, presence detection, door/lock sensors, and home summaries. Credentials are supplied by you (environment variable, openclaw.json, or a secrets file) and are never stored in the skill files.",
  "notes": "SETUP REQUIRED. See README for full instructions.\nToken is read automatically from (in priority order):\n  1. HOME_ASSISTANT_TOKEN environment variable\n  2. openclaw.json env block: HOME_ASSISTANT_URL + HOME_ASSISTANT_TOKEN\n  3. secrets file: ~/.openclaw/workspace/.secrets/home_assistant.token (line 1 = token, optional line 2 = url)\nTransport: TLS verification is always on; for a self-signed cert set HOME_ASSISTANT_CA_CERT. Plain HTTP to a non-loopback host is refused unless HOME_ASSISTANT_ALLOW_HTTP=true.\nGating: every snippet that calls a service - call_service, trigger_automation, camera_snapshot and send_notification - goes through the in-code ha_confirm gate (dry-run unless an explicit CONFIRM token); lock/alarm_control_panel are blocked unless HOME_ASSISTANT_ALLOW_LOCKS=true. ha_get/ha_post are the low-level primitives these gated helpers build on and are not themselves gated.\nAll snippets require _load_config to be executed first in the same script.",
  "setup": {
    "step1": "In Home Assistant: Profile (bottom-left) -> Security -> Long-Lived Access Tokens -> Create Token",
    "step2": "Add to ~/.openclaw/openclaw.json env block: HOME_ASSISTANT_URL and HOME_ASSISTANT_TOKEN",
    "step3": "If using HTTPS with a self-signed cert, set HOME_ASSISTANT_CA_CERT to your CA cert path (TLS stays verified).",
    "step4": "Restart OpenClaw so it picks up the new env (e.g. systemctl --user restart openclaw).",

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

md
"description": "Home Assistant REST API integration for OpenClaw agents. Query and control your smart home via natural language through Telegram or any OpenClaw channel. Covers: lights, switches, climate/heating, temperature sensors, cameras, automations, energy monitoring, EV chargers, presence detection, door/lock sensors, and home summaries. Credentials are supplied by you (environment variable, openclaw.json, or a secrets file) and are never stored in the skill files.",
  "notes": "SETUP REQUIRED. See README for full instructions.\nToken is read automatically from (in priority order):\n  1. HOME_ASSISTANT_TOKEN environment variable\n  2. openclaw.json env block: HOME_ASSISTANT_URL + HOME_ASSISTANT_TOKEN\n  3. secrets file: ~/.openclaw/workspace/.secrets/home_assistant.token (line 1 = token, optional line 2 = url)\nTransport: TLS verification is always on; for a self-signed cert set HOME_ASSISTANT_CA_CERT. Plain HTTP to a non-loopback host is refused unless HOME_ASSISTANT_ALLOW_HTTP=true.\nGating: every snippet that calls a service - call_service, trigger_automation, camera_snapshot and send_notification - goes through the in-code ha_confirm gate (dry-run unless an explicit CONFIRM token); lock/alarm_control_panel are blocked unless HOME_ASSISTANT_ALLOW_LOCKS=true. ha_get/ha_post are the low-level primitives these gated helpers build on and are not themselves gated.\nAll snippets require _load_config to be executed first in the same script.",
  "setup": {
    "step1": "In Home Assistant: Profile (bottom-left) -> Security -> Long-Lived Access Tokens -> Create Token",
    "step2": "Add to ~/.openclaw/openclaw.json env block: HOME_ASSISTANT_URL and HOME_ASSISTANT_TOKEN",
    "step3": "If using HTTPS with a self-signed cert, set HOME_ASSISTANT_CA_CERT to your CA cert path (TLS stays verified).",
    "step4": "Restart OpenClaw so it picks up the new env (e.g. systemctl --user restart openclaw).",

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

md
"description": "Home Assistant REST API integration for OpenClaw agents. Query and control your smart home via natural language through Telegram or any OpenClaw channel. Covers: lights, switches, climate/heating, temperature sensors, cameras, automations, energy monitoring, EV chargers, presence detection, door/lock sensors, and home summaries. Credentials are supplied by you (environment variable, openclaw.json, or a secrets file) and are never stored in the skill files.",
  "notes": "SETUP REQUIRED. See README for full instructions.\nToken is read automatically from (in priority order):\n  1. HOME_ASSISTANT_TOKEN environment variable\n  2. openclaw.json env block: HOME_ASSISTANT_URL + HOME_ASSISTANT_TOKEN\n  3. secrets file: ~/.openclaw/workspace/.secrets/home_assistant.token (line 1 = token, optional line 2 = url)\nTransport: TLS verification is always on; for a self-signed cert set HOME_ASSISTANT_CA_CERT. Plain HTTP to a non-loopback host is refused unless HOME_ASSISTANT_ALLOW_HTTP=true.\nGating: every snippet that calls a service - call_service, trigger_automation, camera_snapshot and send_notification - goes through the in-code ha_confirm gate (dry-run unless an explicit CONFIRM token); lock/alarm_control_panel are blocked unless HOME_ASSISTANT_ALLOW_LOCKS=true. ha_get/ha_post are the low-level primitives these gated helpers build on and are not themselves gated.\nAll snippets require _load_config to be executed first in the same script.",
  "setup": {
    "step1": "In Home Assistant: Profile (bottom-left) -> Security -> Long-Lived Access Tokens -> Create Token",
    "step2": "Add to ~/.openclaw/openclaw.json env block: HOME_ASSISTANT_URL and HOME_ASSISTANT_TOKEN",
    "step3": "If using HTTPS with a self-signed cert, set HOME_ASSISTANT_CA_CERT to your CA cert path (TLS stays verified).",
    "step4": "Restart OpenClaw so it picks up the new env (e.g. systemctl --user restart openclaw).",

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

json
"description": "Home Assistant REST API integration for OpenClaw agents. Query and control your smart home via natural language through Telegram or any OpenClaw channel. Covers: lights, switches, climate/heating, temperature sensors, cameras, automations, energy monitoring, EV chargers, presence detection, door/lock sensors, and home summaries. Credentials are supplied by you (environment variable, openclaw.json, or a secrets file) and are never stored in the skill files.",
  "notes": "SETUP REQUIRED. See README for full instructions.\nToken is read automatically from (in priority order):\n  1. HOME_ASSISTANT_TOKEN environment variable\n  2. openclaw.json env block: HOME_ASSISTANT_URL + HOME_ASSISTANT_TOKEN\n  3. secrets file: ~/.openclaw/workspace/.secrets/home_assistant.token (line 1 = token, optional line 2 = url)\nTransport: TLS verification is always on; for a self-signed cert set HOME_ASSISTANT_CA_CERT. Plain HTTP to a non-loopback host is refused unless HOME_ASSISTANT_ALLOW_HTTP=true.\nGating: every snippet that calls a service - call_service, trigger_automation, camera_snapshot and send_notification - goes through the in-code ha_confirm gate (dry-run unless an explicit CONFIRM token); lock/alarm_control_panel are blocked unless HOME_ASSISTANT_ALLOW_LOCKS=true. ha_get/ha_post are the low-level primitives these gated helpers build on and are not themselves gated.\nAll snippets require _load_config to be executed first in the same script.",
  "setup": {
    "step1": "In Home Assistant: Profile (bottom-left) -> Security -> Long-Lived Access Tokens -> Create Token",
    "step2": "Add to ~/.openclaw/openclaw.json env block: HOME_ASSISTANT_URL and HOME_ASSISTANT_TOKEN",
    "step3": "If using HTTPS with a self-signed cert, set HOME_ASSISTANT_CA_CERT to your CA cert path (TLS stays verified).",
    "step4": "Restart OpenClaw so it picks up the new env (e.g. systemctl --user restart openclaw).",

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
- **Every snippet that calls a service is gated in code, not just prose.** The `call_service`, `trigger_automation`, `camera_snapshot` and `send_notification` snippets run through `ha_confirm`/`ha_call_service` and will not act without an explicit confirmation token; `lock`/`alarm_control_panel` are **blocked unless** you set `HOME_ASSISTANT_ALLOW_LOCKS=true`. `ha_get`/`ha_post` are the low-level primitives these helpers build on and are **not** themselves gated — use the gated snippets (not a raw `ha_post`) for anything that calls a service. Read-only queries (summaries, sensor reads, listings) run without a gate.
- **Cameras are private.** `get_cameras`/`camera_snapshot` return real images and reveal occupancy patterns. `camera_snapshot` is behind the same confirmation gate; snapshots are written owner-only (`0600`). Treat snapshot URLs and saved files as sensitive.
- **Own-instance only.** Point the skill only at a Home Assistant instance you own, with a token you control.
- **Least-privilege token.** Create a dedicated HA user with only the permissions your agent needs (avoid admin), store credentials `chmod 600`, and rotate/revoke the long-lived token periodically or if transport was ever insecure.
- **Verify TLS.** Use `https://`. For a self-signed cert, set `HOME_ASSISTANT_CA_CERT` to your CA so TLS is still verified — there is no option to disable certificate checking. Plain HTTP to a non-loopback host is **refused** unless you set `HOME_ASSISTANT_ALLOW_HTTP=true` (trusted LAN only, token sent unencrypted); loopback (`localhost`/`127.0.0.1`/`::1`) is always allowed.

## Setup

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
- **Every snippet that calls a service is gated in code, not just prose.** The `call_service`, `trigger_automation`, `camera_snapshot` and `send_notification` snippets run through `ha_confirm`/`ha_call_service` and will not act without an explicit confirmation token; `lock`/`alarm_control_panel` are **blocked unless** you set `HOME_ASSISTANT_ALLOW_LOCKS=true`. `ha_get`/`ha_post` are the low-level primitives these helpers build on and are **not** themselves gated — use the gated snippets (not a raw `ha_post`) for anything that calls a service. Read-only queries (summaries, sensor reads, listings) run without a gate.
- **Cameras are private.** `get_cameras`/`camera_snapshot` return real images and reveal occupancy patterns. `camera_snapshot` is behind the same confirmation gate; snapshots are written owner-only (`0600`). Treat snapshot URLs and saved files as sensitive.
- **Own-instance only.** Point the skill only at a Home Assistant instance you own, with a token you control.
- **Least-privilege token.** Create a dedicated HA user with only the permissions your agent needs (avoid admin), store credentials `chmod 600`, and rotate/revoke the long-lived token periodically or if transport was ever insecure.
- **Verify TLS.** Use `https://`. For a self-signed cert, set `HOME_ASSISTANT_CA_CERT` to your CA so TLS is still verified — there is no option to disable certificate checking. Plain HTTP to a non-loopback host is **refused** unless you set `HOME_ASSISTANT_ALLOW_HTTP=true` (trusted LAN only, token sent unencrypted); loopback (`localhost`/`127.0.0.1`/`::1`) is always allowed.

## Setup

Session Persistence

Medium
Category
Rogue Agent
Confidence
72% confidence
Finding

The setup explicitly instructs users to create and persist a long-lived access token in environment/config/secrets files, creating durable credentials that remain valid across sessions and can be abused if the host or OpenClaw configuration is compromised. In this skill's context, that persistent token can expose sensitive home telemetry and enable device control, increasing the consequence of local compromise.

Content

Scanner excerpt · home_assistant.json (reported line 7)May include surrounding context.

json
"description": "Home Assistant REST API integration for OpenClaw agents. Query and control your smart home via natural language through Telegram or any OpenClaw channel. Covers: lights, switches, climate/heating, temperature sensors, cameras, automations, energy monitoring, EV chargers, presence detection, door/lock sensors, and home summaries. Credentials are supplied by you (environment variable, openclaw.json, or a secrets file) and are never stored in the skill files.",
  "notes": "SETUP REQUIRED. See README for full instructions.\nToken is read automatically from (in priority order):\n  1. HOME_ASSISTANT_TOKEN environment variable\n  2. openclaw.json env block: HOME_ASSISTANT_URL + HOME_ASSISTANT_TOKEN\n  3. secrets file: ~/.openclaw/workspace/.secrets/home_assistant.token (line 1 = token, optional line 2 = url)\nTransport: TLS verification is always on; for a self-signed cert set HOME_ASSISTANT_CA_CERT. Plain HTTP to a non-loopback host is refused unless HOME_ASSISTANT_ALLOW_HTTP=true.\nGating: every snippet that calls a service - call_service, trigger_automation, camera_snapshot and send_notification - goes through the in-code ha_confirm gate (dry-run unless an explicit CONFIRM token); lock/alarm_control_panel are blocked unless HOME_ASSISTANT_ALLOW_LOCKS=true. ha_get/ha_post are the low-level primitives these gated helpers build on and are not themselves gated.\nAll snippets require _load_config to be executed first in the same script.",
  "setup": {
    "step1": "In Home Assistant: Profile (bottom-left) -> Security -> Long-Lived Access Tokens -> Create Token",
    "step2": "Add to ~/.openclaw/openclaw.json env block: HOME_ASSISTANT_URL and HOME_ASSISTANT_TOKEN",
    "step3": "If using HTTPS with a self-signed cert, set HOME_ASSISTANT_CA_CERT to your CA cert path (TLS stays verified).",
    "step4": "Restart OpenClaw so it picks up the new env (e.g. systemctl --user restart openclaw).",

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · home_assistant.json (reported line 14)May include surrounding context.

json
"step5": "Test: ask your bot 'home summary' or 'what is the temperature?'"
  },
  "snippets": {
    "_load_config": "import json, requests, os, sys\nfrom pathlib import Path\n\ndef _load_ha_config():\n    # Priority 1: system environment variables\n    url   = os.environ.get(\"HOME_ASSISTANT_URL\", \"\").strip()\n    token = os.environ.get(\"HOME_ASSISTANT_TOKEN\", \"\").strip()\n    # Priority 2: openclaw.json env block\n    if not token:\n        oc = Path.home() / \".openclaw/openclaw.json\"\n        if oc.exists():\n            try:\n                env = json.loads(oc.read_text()).get(\"env\", {})\n                url   = url   or env.get(\"HOME_ASSISTANT_URL\",   \"\").strip()\n                token = token or env.get(\"HOME_ASSISTANT_TOKEN\", \"\").strip()\n            except Exception: pass\n    # Priority 3: secrets file (line1 = token, optional line2 = url)\n    if not token:\n        try:\n            sec = Path.home() / \".openclaw/workspace/.secrets/home_assistant.token\"\n            if sec.exists():\n                parts = sec.read_text().splitlines()\n                if parts:\n                    token = token or parts[0].strip()\n                    if len(parts) > 1 and not url:\n                        url = parts[1].strip()\n        except Exception: pass\n    if not token:\n        raise RuntimeError(\n            \"HOME_ASSISTANT_TOKEN not configured. \"\n            \"Add to openclaw.json env block, set HOME_ASSISTANT_TOKEN env var, \"\n            \"or create ~/.openclaw/workspace/.secrets/home_assistant.token\"\n        )\n    return (url or \"http://homeassistant.local:8123\").rstrip(\"/\"), token\n\ndef _ssl_verify():\n    # TLS verification is always on. For a self-signed cert on a trusted LAN,\n    # point HOME_ASSISTANT_CA_CERT at your CA so HTTPS still verifies.\n    ca = os.environ.get(\"HOME_ASSISTANT_CA_CERT\", \"\").strip()\n    return ca if ca else True\n\nHA_URL, HA_TOKEN = _load_ha_config()\n_ha_host = HA_URL.split(\"://\", 1)
...[truncated 26 chars]

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger list includes broad natural-language phrases such as 'turn on the', 'turn off the', and 'what is the temperature' that can cause the skill to activate in routine conversation or in messages from untrusted channels. In this skill, unintended activation is more dangerous than usual because the skill can access occupancy, cameras, automations, and issue state-changing Home Assistant actions after follow-up confirmation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.