Back to skill

Security audit

Home Assistant Control

Security checks for vulnerabilities and agentic risk

Overview

This Home Assistant skill is coherent and not malicious, but it needs Review because it can control physical devices with a long-lived token and may send that token over HTTP if configured that way.

Install only if you are comfortable giving the skill a Home Assistant token that can inspect and control your configured devices. Use HTTPS for any public or remote URL, keep the token narrowly permissioned where possible, avoid --yes for locks, alarms, covers, doors, or climate actions unless you explicitly requested that action, and treat generated reference files as private household metadata.

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

Warning
Location
scripts/ha_call.sh:42
Finding
Long-Lived Home Assistant Token Can Be Transmitted over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ha_call.sh:42-65` **Vulnerability Type**: Plaintext transmission of sensitive authentication credentials **Risk Level**: Medium ### Vulnerable Code ```bash for base in "${CANDIDATES[@]}"; do if [[ "$base" != http://* && "$base" != https://* ]]; then echo "Error: Invalid URL scheme in '$base'. Use http:// or https://" >&2 exit 1 fi done attempt_request() { local base_url="$1" if [[ "$METHOD" == "GET" ]]; then curl -sS \ --connect-timeout 8 \ --max-time 20 \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ "$base_url$PATH_PART" else curl -sS -X "$METHOD" \ --connect-timeout 8 \ --max-time 20 \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ -d "$DATA" \ "$base_url$PATH_PART" fi } ``` ### Technical Analysis The URL validation explicitly accepts both HTTPS and plaintext HTTP destinations. Every request then places the long-lived Home Assistant token in the `Authorization` header. Plaintext HTTP provides neither transport confidentiality nor server authentication. Although HTTP can be reasonable for an intentionally trusted local Home Assistant network, the implementation does not restrict it to loopback, link-local, or private-network addresses. It can therefore send the token to a public or otherwise untrusted HTTP endpoint configured through `HA_URL`, `HA_URL_LOCAL`, or `HA_URL_PUBLIC`. The network operation itself is necessary for the declared functionality. In particular, `scripts/ha_entity_find.sh` legitimately calls `GET /api/states` and filters the returned entity data locally. The security issue is not the presence of network access, but the absence of sufficiently strict transport protection for the bearer credential. ### Attack Path 1. A user configures a Home Assistant URL using `http://`, or an attacker modifies the relevant enviro ...[truncated 1159 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require HTTPS for `HA_URL_PUBLIC` and any destination that is not demonstrably local. 2. If plaintext local access must remain supported, require an explicit opt-in such as `HA_ALLOW_INSECURE_LOCAL_HTTP=1`. 3. Resolve the hostname and permit HTTP only for loopback, link-local, or approved private-network destinations. Account for DNS rebinding and redirects. 4. Add `--proto '=https'` for public requests and disable redirects, or use `--proto-redir '=https'` if redirects are required. 5. Consider certificate pinning or a configurable private certificate authority for sensitive deployments. 6. Emit a prominent warning whenever HTTP is explicitly enabled. 7. Document that the Home Assistant token should use the minimum permissions necessary and should be rotated immediately if transmitted over an untrusted network. 8. Apply the same URL and transport validation consistently in `scripts/self_check.sh`. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/self_check.sh:87
Finding
Predictable Temporary Error File Enables Local Symlink Clobbering<![CDATA[ ## Vulnerability Details **File Location**: `scripts/self_check.sh:87-105` **Vulnerability Type**: Insecure predictable temporary-file creation **Risk Level**: Low ### Vulnerable Code ```bash HTTP_CODE="$(curl -sS -o "$TMP_BODY" -w "%{http_code}" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ "$base/api/states" 2>/tmp/ha_self_check_err.$$ || true)" # curl transport failure => try fallback if [[ "$HTTP_CODE" == "000" || -z "$HTTP_CODE" ]]; then LAST_TRANSPORT_ERR="$(cat /tmp/ha_self_check_err.$$ 2>/dev/null || true)" if [[ "$i" -lt $((${#CANDIDATES[@]} - 1)) ]]; then warn "Primary URL unreachable, trying fallback..." continue fi fi USED_URL="$base" break done rm -f /tmp/ha_self_check_err.$$ 2>/dev/null || true ``` ### Technical Analysis The script redirects curl diagnostics to `/tmp/ha_self_check_err.$$`, where `$$` is the shell process ID. Process IDs are predictable and the shared `/tmp` directory is normally writable by other local users. The shell opens the path for output without securely creating it first. If another local user pre-creates that pathname as a symbolic link, the redirection follows the link and truncates or overwrites its target using the privileges of the user running the Skill. The later `rm -f` only removes the pathname and does not prevent the earlier unsafe open. The script already uses `mktemp` safely for the response body, so the separate predictable error file is unnecessary. ### Attack Path 1. A local attacker predicts or observes a likely process ID for an upcoming `self_check.sh` execution. 2. The attacker creates `/tmp/ha_self_check_err.<PID>` as a symbolic link to a file writable by the victim account. 3. The victim runs `scripts/self_check.sh` with the predicted PID. 4. Shell redirection opens the symbolic-link target with truncation before curl starts. 5. The target file is truncated and may receive curl diagnostic text. 6. T ...[truncated 810 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Allocate the error file using `mktemp`: ```bash TMP_BODY="$(mktemp)" TMP_ERR="$(mktemp)" trap 'rm -f "$TMP_BODY" "$TMP_ERR"' EXIT ``` 2. Redirect curl diagnostics to the securely created path: ```bash HTTP_CODE="$(curl -sS -o "$TMP_BODY" -w "%{http_code}" \ -H "Authorization: Bearer $HA_TOKEN" \ -H "Content-Type: application/json" \ "$base/api/states" 2>"$TMP_ERR" || true)" ``` 3. Read diagnostics from `"$TMP_ERR"` and rely on the existing `EXIT` trap for cleanup. 4. Set a restrictive `umask`, such as `umask 077`, before creating temporary files containing operational data. 5. Avoid constructing any temporary filename from process IDs, timestamps, usernames, or other predictable values. 6. Do not run the Skill as root or another privileged system account unless strictly necessary. ]]>
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared purpose focuses on controlling and inspecting Home Assistant, but the skill also maintains local reference and naming-context files derived from Home Assistant data. This hidden persistence expands the data-handling surface by writing potentially sensitive household metadata to disk, which users may not expect from the description and which could be accessed later by other tools or sessions.

Credential Access

High
Category
Privilege Escalation
Content
# Home Assistant Control

Use Home Assistant REST API with a long-lived access token.

## Requirements
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Ae1

High
Category
analysis-evasion
Content
- `scripts/ha_call.sh` and `scripts/self_check.sh` load env file only when `HA_ENV_FILE` is provided.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/ha_call.sh` and `scripts/self_check.sh` load env file only when `HA_ENV_FILE` is provided.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/ha_entity_find.sh` — search entities by partial entity id or friendly name.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/ha_entity_find.sh` — search entities by partial entity id or friendly name.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/ha_entity_find.sh` — search entities by partial entity id or friendly name.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Tool Parameter Abuse

High
Category
Tool Misuse
Content
break
done

rm -f /tmp/ha_self_check_err.$$ 2>/dev/null || true

if [[ -z "$USED_URL" ]]; then
  err "No HTTP status returned from any configured URL."
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Session Persistence

Medium
Category
Rogue Agent
Content
### Example private env file

Create a private file (example `~/.openclaw/private/home-assistant.env`), then set:

```bash
export HA_ENV_FILE="$HOME/.openclaw/private/home-assistant.env"
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.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill advertises shell-based scripts and operational capabilities but does not declare any explicit tool scope or permissions boundary. In agent environments, missing scope declarations can let a broadly empowered runtime execute shell actions beyond what users or platform policy expect, increasing the risk of unintended command execution or misuse.

External Transmission

Medium
Category
Data Exfiltration
Content
local base_url="$1"

  if [[ "$METHOD" == "GET" ]]; then
    curl -sS \
      --connect-timeout 8 \
      --max-time 20 \
      -H "Authorization: Bearer $HA_TOKEN" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script performs network calls with curl and includes an Authorization bearer token header, and POST requests may also send arbitrary JSON payload data. While the code validates inputs and logs fallback behavior, it provides no confirmation prompt, user-facing notice, or explanatory comment/docstring warning that credentials and potentially sensitive data will be transmitted to a remote endpoint.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
Usage: ha_safe_action.sh <domain> <service> <entity_id> [json_payload] [options]

Options:
  --yes         Skip confirmation prompts
  --dry-run     Print payload only, do not execute
  -h, --help    Show this help
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Static analysis

No suspicious patterns detected.