Back to skill

Security audit

Homebridge

Security checks for vulnerabilities and agentic risk

Overview

The skill appears purpose-aligned, but it deserves review because it can use stored smart-home credentials to immediately change physical device state and does not enforce HTTPS.

Review before installing. Use this only with a trusted Homebridge instance, configure an https:// URL, prefer a least-privileged Homebridge account, protect the credential file, and understand that set commands can immediately change real devices such as switches, fans, and thermostats.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/homebridge_api.py:50
Finding

Homebridge credentials and bearer tokens may be transmitted over unencrypted HTTP

Content
View full analysis
dict: """Make HTTP request to Homebridge API.""" headers = {"Content-Type": "application/json"} if token: headers["Authorization"] = f"Bearer {token}" body = json.dumps(data).encode() if data else None req = Request(url, data=body, headers=headers, method=method) try: with urlopen(req, timeout=30) as resp: return json.loads(resp.read().decode()) except HTTPError as e: error_body = e.read().decode() if e.fp else "" print(f"HTTP Error {e.code}: {e.reason}", file=sys.stderr) if error_body: print(f"Response: {error_body}", file=sys.stderr) sys.exit(1) except URLError as e: print(f"Connection error: {e.reason}", file=sys.stderr) sys.exit(1) def authenticate(base_url: str, username: str, password: str) -> str: """Authenticate and return access token.""" url = f"{base_url}/api/auth/login" data = {"username": username, "password": password} response = make_request(url, method="POST", data=data) return response.get("access_token") ``` The configured URL is used without validating its scheme: ```python config = load_config() base_url = config["url"].rstrip("/") username = config["username"] password = config["password"] # Authenticate token = authenticate(base_url, username, password) ``` ### Technical Analysis The script reads an administrative username and password from `~/.clawdbot/credentials/homebridge.json` and sends them to the configured Homebridge URL. After authentication, it sends the returned bearer token in the `Authorization` header on subsequent API requests. ...[truncated 2564 chars]
Remediation
View remediation
str: url = raw_url.rstrip("/") parsed = urlsplit(url) if parsed.scheme.lower() != "https": raise ValueError("Homebridge URL must use HTTPS") if not parsed.hostname: raise ValueError("Homebridge URL must include a valid hostname") if parsed.username or parsed.password: raise ValueError("Credentials must not be embedded in the URL") return url ``` Apply it when reading the configuration: ```python try: base_url = validate_base_url(config["url"]) except ValueError as e: print(f"Error: {e}", file=sys.stderr) sys.exit(1) ``` 2. **Do not silently fall back to HTTP.** If plaintext access is required for a narrowly defined loopback-only deployment, require an explicit insecure opt-in and restrict it to verified loopback addresses. Display a prominent warning. Plaintext access to LAN or remote hosts should remain prohibited. 3. **Preserve TLS certificate verification.** Do not use an unverified SSL context. For local deployments using a private or self-signed certificate, support a configurable trusted CA certificate instead of disabling verification. 4. **Use a least-privileged Homebridge account.** The configured account should have only the API permissions required to enumerate and control intended accessories, where supported. 5. **Protect the credential file.** Require or warn when `~/.clawdbot/credentials/homebridge.json` is readable by group or other users. Recommended permissions are `0600`, with the parent credentials directory restricted to the owning user. 6. **Limit sensitive error output.** Avoid printing arbitrary authentication response bodies because a server or intermediary could retu ...[truncated 257 chars]
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (7)

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/homebridge_api.py (reported line 74)May include surrounding context.

python
def authenticate(base_url: str, username: str, password: str) -> str:
    """Authenticate and return access token."""
    url = f"{base_url}/api/auth/login"
    data = {"username": username, "password": password}
    response = make_request(url, method="POST", data=data)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill performs network operations against a Homebridge REST API but does not declare any explicit tool scope or allowed-tools metadata. This weakens runtime policy enforcement and transparency, making it easier for a skill capable of changing physical device state to be invoked without clear permission boundaries.

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

bash
# Get auth token
TOKEN=$(curl -s -X POST "${HOMEBRIDGE_URL}/api/auth/login" \
  -H "Content-Type: application/json" \
  -d "{\"username\":\"${HOMEBRIDGE_USERNAME}\",\"password\":\"${HOMEBRIDGE_PASSWORD}\"}" \
  | jq -r '.access_token')

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill describes commands that can turn devices on or off and modify thermostat or fan settings, but it does not warn users that these actions affect the physical environment and may create safety, comfort, or energy risks. In a home automation context, silent device-control capability is more dangerous because users may not appreciate that routine-looking API calls can unlock hazardous real-world outcomes.

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

bash
# Turn on a light/switch
curl -s -X PUT "${HOMEBRIDGE_URL}/api/accessories/{uniqueId}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"characteristicType": "On", "value": true}'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code exposes a set operation that sends a PUT request to change an accessory characteristic, which can directly alter device state in the user's environment. There is no confirmation prompt, cautionary print/log message, or other user-facing disclosure before executing the change.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module docstring says credentials are read from ~/.clawdbot/clawdbot.json under skills.entries.homebridge, but load_config() actually reads ~/.clawdbot/credentials/homebridge.json. This is an active contradiction between the documented setup and the implemented behavior, which can mislead operators about where sensitive credentials are sourced from.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.