Back to skill

Security audit

Xiaomi Home Control

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent smart-home software, but it exposes high-impact home-control and credential handling with under-scoped network binding, privileged containers, and persistence.

Review before installing. Use only a least-privilege Home Assistant token, protect or rotate it, bind the MCP server explicitly to loopback, avoid privileged/host-network Docker unless you know you need it, and do not enable persistent startup until the LaunchAgent contents and uninstall steps are clear.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (6)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ha-mcp-server/src/http-server.mjs:183
Finding

Smart-home control API binds to all network interfaces despite localhost-only security claims

Content
View full analysis
{ if (req.method === "OPTIONS") { res.writeHead(200, { "Access-Control-Allow-Origin": ALLOWED_ORIGIN, "Access-Control-Allow-Methods": "POST, GET, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization" }); res.end(); return; } // Reject requests from non-localhost origins const origin = req.headers["origin"] || req.headers["Origin"]; if (origin && !origin.startsWith(ALLOWED_ORIGIN)) { res.writeHead(403, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Forbidden: cross-origin request denied" })); return; } // Require authentication for all tool calls if (req.method === "POST" && !checkAuth(req)) { res.writeHead(401, { "Content-Type": "application/json", "WWW-Authenticate": "Bearer" }); res.end(JSON.stringify({ error: "Unauthorized: valid Bearer token required" })); return; } ``` ```js server.listen(PORT, () => { console.error(`HA MCP Server running on http://localhost:${PORT}`); }); ``` ### Technical Analysis Calling `server.listen(PORT)` without a hostname normally listens on the unspecified address, commonly `::` and/or `0.0.0.0`, rather than exclusively on the loopback interface. Consequently, the smart-home control API may be reachable from other systems on the LAN or other attached networks. This conflicts with the security guarantees in `SKILL.md` and `README.md`, which state that the server only accepts localhost requests and binds to localhost. The `Origin` header is not a network access control mechanism. Non-browser clients can omit it entirely. In addition, `origin.startsWith("http://localhost")` accepts misleading origins such as `http://localhost.attacker.exam ...[truncated 1362 chars]
Remediation
View remediation
{ console.error(`HA MCP Server running on http://127.0.0.1:${PORT}`); }); ``` If IPv6 is required, create an explicitly controlled loopback listener for `::1`. 2. Do not treat CORS or `Origin` validation as network authentication. If origin checking is retained, parse the URL and require exact allowed origins rather than using `startsWith`. 3. Use a separate, randomly generated MCP client secret instead of reusing the Home Assistant long-lived access token. 4. Introduce per-tool authorization and explicit confirmation for operations such as `lock_unlock`. 5. Add firewall documentation and an opt-in configuration if remote access is intentionally supported. Remote access should use TLS or a mutually authenticated local proxy. 6. Fail startup when the server cannot confirm that it is bound only to an approved interface. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
docker-compose.yml:4
Finding

Home Assistant container is granted privileged host access and host networking

Content
View full analysis
Remediation
View remediation

T06 · System Persistence

Error
Location
scripts/setup.sh:77
Finding

Setup attempts to install a persistent macOS LaunchAgent without an opt-in lifecycle

Content
View full analysis
"$PLIST_DST" launchctl load "$PLIST_DST" 2>/dev/null || true echo "✓ HA MCP Server installed as LaunchAgent" ``` The setup also starts another persistent service earlier through Docker, and the Compose configuration specifies: ```yaml restart: unless-stopped ``` ### Technical Analysis The setup writes a LaunchAgent definition into `~/Library/LaunchAgents` and loads it with `launchctl`. A LaunchAgent is a cross-session persistence mechanism intended to start or maintain a process under the user's account. An always-on service can be relevant to smart-home control, but automatic persistence should be clearly disclosed, explicitly selected, and accompanied by removal instructions. The script does not offer a non-persistent setup mode or an uninstall path. The audited package does not contain the referenced `scripts/ha-mcp-server/ai.openclaw.ha-mcp.plist`. Because `setup.sh` uses `set -e`, the `sed` command will fail as packaged before the LaunchAgent can be installed. This limits immediate exploitability but also means setup can stop after Home Assistant has already been started with `restart: unless-stopped`, leaving a partially installed persistent environment. ### Attack Path 1. The user runs `scripts/setup.sh`. 2. The script starts Home Assistant with an automatic restart policy. 3. The script attempts to create `~/Library/LaunchAgents/ai.openclaw.ha-mcp.plist`. 4. In the audited package, the missing source plist causes setup to terminate after partial installation. 5. If the missing ...[truncated 625 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ha-mcp-server/src/http-server.mjs:22
Finding

Long-lived Home Assistant bearer token can be sent to an arbitrary plaintext endpoint

Content
View full analysis
" header function checkAuth(req) { const auth = req.headers["authorization"] || req.headers["Authorization"]; if (!auth || !auth.startsWith("Bearer ")) return false; const token = auth.slice("Bearer ".length); return token === HA_TOKEN; } // ============================================================================ // HA API // ============================================================================ async function haFetch(endpoint, options = {}) { const url = `${HA_URL}/api${endpoint}`; const response = await fetch(url, { ...options, headers: { "Authorization": `Bearer ${HA_TOKEN}`, "Content-Type": "application/json", ...options.headers, }, }); if (!response.ok) throw new Error(`HA API error: ${response.status}`); return response.json(); } ``` ### Technical Analysis `HA_URL` is loaded from a writable `.env` file and is not constrained to loopback, a trusted host, or HTTPS. Every Home Assistant API request automatically adds the long-lived token to the `Authorization` header. The default value is local HTTP, which is reasonable when both processes run on the same host. However, a changed value such as `http://attacker.example` causes the token to be transmitted over plaintext HTTP to that destination. This contradicts the documentation's assertion that the token is never sent anywhere other than local Home Assistant. This is particularly sensitive because the same token i ...[truncated 1153 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup.sh:57
Finding

Setup stores a long-lived credential without protected input or enforced file permissions

Content
View full analysis
"$SCRIPT_DIR/.env" echo "HA_TOKEN=$HA_TOKEN" >> "$SCRIPT_DIR/.env" echo "PORT=3002" >> "$SCRIPT_DIR/.env" echo "✓ Created .env file" ``` ### Technical Analysis `read -r HA_TOKEN` does not suppress terminal echo, so the long-lived credential is visible while entered. The script also creates `.env` using the user's ambient `umask` and never enforces restrictive permissions such as mode `0600`. The project documentation repeatedly says that `.env` is gitignored, but no `.gitignore` file appears in the audited directory structure. Therefore, the repository does not itself enforce the stated protection against accidental commits. Because the file is stored inside the Skill directory, it may also be copied during backup, packaging, synchronization, or source-control operations. ### Attack Path 1. The user runs the setup script and enters the Home Assistant token. 2. The token is displayed on the terminal during entry. 3. The script writes it to `scripts/ha-mcp-server/.env` using permissions determined by the current `umask`. 4. Another local account, backup process, synchronization tool, or source-control operation reads or copies the file. 5. The exposed token is used to access Home Assistant or the MCP API. ### Impact Assessment A disclosed token can grant the Home Assistant permissions assigned to the token owner. The resulting scope may include sensitive sensor data, household presence information, appliance control, scenes, speakers, and smart-lock operations. ...[truncated 95 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ha-mcp-server/src/http-server.mjs:204
Finding

Network request bodies are buffered without size or rate limits

Content
View full analysis
body += chunk); req.on("end", async () => { try { const json = JSON.parse(body); const jsonrpc = json.jsonrpc || "2.0"; const method = json.method; const params = json.params || {}; const responseId = json.id; if (method === "tools/list") { const toolList = Object.keys(tools).map(name => ({ name, description: "", inputSchema: { type: "object" } })); res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ jsonrpc, id: responseId, result: { tools: toolList } })); return; } if (method === "tools/call") { const toolName = params.name; const args = params.arguments || {}; if (!tools[toolName]) { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ jsonrpc, id: responseId, error: { code: -32601, message: `Tool ${toolName} not found` } })); return; } try { const result = await tools[toolName](args); res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ jsonrpc, id: responseId, result })); } catch (err) { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ jsonrpc, id: responseId, error: { code: -32603, message: err.message } })); } return; } ``` ### Technical Analysis The server appends every incoming chunk to a JavaScript string and performs no maximum-length check. It also has no application-level rate limit, concurrency limit, or explicit request timeout. Because the server may bind to all interfaces, an authenticated network client or compromised local ...[truncated 1048 chars]
Remediation
View remediation
{ size += chunk.length; if (size > MAX_BODY) { res.writeHead(413); res.end(); req.destroy(); return; } chunks.push(chunk); }); ``` 3. Configure `requestTimeout`, `headersTimeout`, and keep-alive limits. 4. Add rate and concurrency limits per client. 5. Bind the service to loopback so the protection boundary does not depend solely on bearer authentication. 6. Validate `Content-Type` and reject unsupported request methods or encodings early. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (65)

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
### 3. Create Access Token

1. HA profile → **Long-Lived Access Tokens** → Create Token
2. Copy and save it

### 4. Install Control Server

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

md
NOTE: Requires Home Assistant (Docker, localhost:8123) and Xiaomi devices paired with Mi Home.

Required credentials:
- `HA_TOKEN`: Long-Lived Access Token from Home Assistant, stored in `.env` (gitignored). Used as Bearer token to authenticate MCP server requests. Never sent to any external service.

Security:
- MCP server only accepts requests from localhost

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

md
NOTE: Requires Home Assistant (Docker, localhost:8123) and Xiaomi devices paired with Mi Home.

Required credentials:
- `HA_TOKEN`: Long-Lived Access Token from Home Assistant, stored in `.env` (gitignored). Used as Bearer token to authenticate MCP server requests. Never sent to any external service.

Security:
- MCP server only accepts requests from localhost

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

md
NOTE: Requires Home Assistant (Docker, localhost:8123) and Xiaomi devices paired with Mi Home.

Required credentials:
- `HA_TOKEN`: Long-Lived Access Token from Home Assistant, stored in `.env` (gitignored). Used as Bearer token to authenticate MCP server requests. Never sent to any external service.

Security:
- MCP server only accepts requests from localhost

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

md
NOTE: Requires Home Assistant (Docker, localhost:8123) and Xiaomi devices paired with Mi Home.

Required credentials:
- `HA_TOKEN`: Long-Lived Access Token from Home Assistant, stored in `.env` (gitignored). Used as Bearer token to authenticate MCP server requests. Never sent to any external service.

Security:
- MCP server only accepts requests from localhost

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 · references/installation.md (reported line 53)May include surrounding context.

md
NOTE: Requires Home Assistant (Docker, localhost:8123) and Xiaomi devices paired with Mi Home.

Required credentials:
- `HA_TOKEN`: Long-Lived Access Token from Home Assistant, stored in `.env` (gitignored). Used as Bearer token to authenticate MCP server requests. Never sent to any external service.

Security:
- MCP server only accepts requests from localhost

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

sh
NOTE: Requires Home Assistant (Docker, localhost:8123) and Xiaomi devices paired with Mi Home.

Required credentials:
- `HA_TOKEN`: Long-Lived Access Token from Home Assistant, stored in `.env` (gitignored). Used as Bearer token to authenticate MCP server requests. Never sent to any external service.

Security:
- MCP server only accepts requests from localhost

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

sh
NOTE: Requires Home Assistant (Docker, localhost:8123) and Xiaomi devices paired with Mi Home.

Required credentials:
- `HA_TOKEN`: Long-Lived Access Token from Home Assistant, stored in `.env` (gitignored). Used as Bearer token to authenticate MCP server requests. Never sent to any external service.

Security:
- MCP server only accepts requests from localhost

Privileged Kubernetes Workload

High
Category
Tool Misuse
Confidence
98% confidence
Finding

Running the Home Assistant container with privileged: true grants it broad kernel capabilities and near-host-level access, greatly expanding the blast radius of any compromise in Home Assistant, its integrations, or dependencies. Combined with host networking, this setup reduces isolation and can enable host modification, device access, or lateral movement if the container is exploited.

Content

Scanner excerpt · docker-compose.yml (reported line 8)May include surrounding context.

yaml
homeassistant:
    container_name: homeassistant
    image: ghcr.io/home-assistant/home-assistant:stable
    privileged: true
    network_mode: host
    volumes:
      - ./config:/config

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 · references/api-notes.md (reported line 5)May include surrounding context.

Authentication

All API requests require a Long-Lived Access Token in the Authorization header:

text
Authorization: Bearer YOUR_TOKEN_HERE

Known Vulnerable Dependency: fast-uri==3.1.0 — 7 advisory(ies): CVE-2026-13676 (fast-uri vulnerable to host confusion via failed IDN canonicalization); CVE-2026-18446 (fast-uri vulnerable to host confusion via backslash authority introducer); CVE-2026-75975 (fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat) +4 more

High
Category
Supply Chain
Confidence
84% confidence
Finding

fast-uri 3.1.0 is present and carries multiple URI parsing issues including host confusion and possible SSRF-related normalization flaws. Since this package is used by ajv, the practical risk depends on whether the application validates or dereferences attacker-influenced URIs, but flawed URI canonicalization can undermine allowlists and trust decisions.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: hono==4.12.14 — 16 advisory(ies): CVE-2026-47676 (Hono: app.mount() strips mount prefix using undecoded path, causing incorrect ro); CVE-2026-47675 (Hono: Cookie helper does not sanitize sameSite and priority, allowing Set-Cookie); CVE-2026-71848 (Hono: Algorithmic Complexity DoS in Language Middleware) +13 more

High
Category
Supply Chain
Confidence
88% confidence
Finding

hono 4.12.14 is directly present through the MCP SDK and is reported with multiple advisories affecting routing, cookie handling, and DoS-related behavior. Because this skill appears to run an MCP server and includes HTTP-serving components, framework-level flaws in request handling are more relevant than they would be in a purely local CLI-only package.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ip-address==10.1.0 — 2 advisory(ies): CVE-2026-69192 (ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco); CVE-2026-42338 (ip-address has XSS in Address6 HTML-emitting methods)

High
Category
Supply Chain
Confidence
80% confidence
Finding

ip-address 10.1.0 is flagged for parsing inconsistencies and XSS in HTML-emitting methods. Here it is introduced by express-rate-limit, so the XSS vector may be less relevant unless those rendering helpers are used, but IP parsing ambiguities can still weaken rate-limit bypass protections or address-based policy checks if exposed to attacker-controlled inputs.

Content

No source excerpt is available for this finding.

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/ha-mcp-server/src/call-tool.mjs (reported line 12)May include surrounding context.

js
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const envPath = path.resolve(__dirname, "../.env");
const env = {};
try {
  const lines = readFileSync(envPath, "utf8").split("\n");

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/ha-mcp-server/src/http-server.mjs (reported line 12)May include surrounding context.

js
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const envPath = path.resolve(__dirname, "../.env");
const env = {};
try {
  const lines = readFileSync(envPath, "utf8").split("\n");

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/setup.sh (reported line 57)May include surrounding context.

sh
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const envPath = path.resolve(__dirname, "../.env");
const env = {};
try {
  const lines = readFileSync(envPath, "utf8").split("\n");

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/setup.sh (reported line 65)May include surrounding context.

sh
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const envPath = path.resolve(__dirname, "../.env");
const env = {};
try {
  const lines = readFileSync(envPath, "utf8").split("\n");

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

md
const [key, ...vals] = line.split("=");
    if (key && vals.length) env[key.trim()] = vals.join("=").trim();
  }
} catch (e) { /* no .env */ }

const HA_URL = env.HA_URL || "http://localhost:8123";
const HA_TOKEN = env.HA_TOKEN || "";

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

md
const [key, ...vals] = line.split("=");
    if (key && vals.length) env[key.trim()] = vals.join("=").trim();
  }
} catch (e) { /* no .env */ }

const HA_URL = env.HA_URL || "http://localhost:8123";
const HA_TOKEN = env.HA_TOKEN || "";

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 · references/installation.md (reported line 56)May include surrounding context.

md
const [key, ...vals] = line.split("=");
    if (key && vals.length) env[key.trim()] = vals.join("=").trim();
  }
} catch (e) { /* no .env */ }

const HA_URL = env.HA_URL || "http://localhost:8123";
const HA_TOKEN = env.HA_TOKEN || "";

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/ha-mcp-server/src/call-tool.mjs (reported line 20)May include surrounding context.

js
const [key, ...vals] = line.split("=");
    if (key && vals.length) env[key.trim()] = vals.join("=").trim();
  }
} catch (e) { /* no .env */ }

const HA_URL = env.HA_URL || "http://localhost:8123";
const HA_TOKEN = env.HA_TOKEN || "";

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/ha-mcp-server/src/http-server.mjs (reported line 20)May include surrounding context.

js
const [key, ...vals] = line.split("=");
    if (key && vals.length) env[key.trim()] = vals.join("=").trim();
  }
} catch (e) { /* no .env */ }

const HA_URL = env.HA_URL || "http://localhost:8123";
const HA_TOKEN = env.HA_TOKEN || "";

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/setup.sh (reported line 66)May include surrounding context.

sh
const [key, ...vals] = line.split("=");
    if (key && vals.length) env[key.trim()] = vals.join("=").trim();
  }
} catch (e) { /* no .env */ }

const HA_URL = env.HA_URL || "http://localhost:8123";
const HA_TOKEN = env.HA_TOKEN || "";

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/setup.sh (reported line 68)May include surrounding context.

sh
const [key, ...vals] = line.split("=");
    if (key && vals.length) env[key.trim()] = vals.join("=").trim();
  }
} catch (e) { /* no .env */ }

const HA_URL = env.HA_URL || "http://localhost:8123";
const HA_TOKEN = env.HA_TOKEN || "";

Privileged Container / Container Escape

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

Running the Home Assistant container with --privileged grants the container extensive access to the host, greatly increasing the consequences of a container compromise or malicious image behavior. In a smart-home setup, this is especially sensitive because the service is network-facing and handles automation data and credentials, so host-level impact could extend beyond the application itself.

Content

Scanner excerpt · scripts/setup.sh (reported line 35)May include surrounding context.

sh
cd "$SKILL_DIR"
docker compose up -d 2>/dev/null || docker run -d \
  --name homeassistant \
  --privileged \
  -p 8123:8123 \
  -v ~/homeassistant/config:/config \
  -v /etc/localtime:/etc/localtime:ro \

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/ha-mcp-server/src/call-tool.mjs:22