Back to skill

Security audit

communication-mqtt

Security checks for vulnerabilities and agentic risk

Overview

This is a small local MQTT messaging skill with clear purpose, but users should treat published agent details as visible to anyone who can access the broker.

Install only in a controlled local environment with a trusted MQTT broker. Prefer a virtual environment and pinned dependencies, extract only the needed agent_id instead of printing the full OpenClaw config, avoid publishing sensitive roles or activities, and configure broker authentication, ACLs, TLS when crossing trust boundaries, and clear rules for retained messages.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (4)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:27
Finding
OpenClaw Configuration Is Unnecessarily Exposed to Terminal Output<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:27-30` **Vulnerability Type**: Excessive access to potentially sensitive configuration **Risk Level**: Medium ### Vulnerable Code ```markdown #### 자신의 `agent_id` 확인 ``` cat ~/.openclaw/openclaw.json ``` ``` ### Technical Analysis The documentation directs the user or executing agent to print the entire `~/.openclaw/openclaw.json` file merely to identify an `agent_id`. This violates the principle of least privilege because all fields in the configuration are disclosed even though only one field is required. The audit did not establish the exact contents of this configuration file. Nevertheless, configuration files can contain unrelated operational or sensitive values. Printing the complete file makes every contained field visible to the terminal, command logs, session recordings, agent context, and any process collecting standard output. ### Attack Path 1. A user or agent follows the documented setup procedure. 2. The command `cat ~/.openclaw/openclaw.json` reads the entire OpenClaw configuration. 3. The complete contents are emitted to standard output. 4. Terminal logging, session capture, shared agent context, or another observer obtains fields unrelated to discovering `agent_id`. 5. Any exposed sensitive values can be used according to the permissions those values provide. ### Impact Assessment This issue provides no direct privilege escalation by itself. Its impact depends on the actual contents of the local configuration file. At minimum, it exposes configuration metadata beyond the task's needs. If credentials or other sensitive settings are present, their associated access scope could also be exposed. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Replace the full-file `cat` command with strict extraction of only the required field. - Use an appropriate JSON parser, for example: ```bash jq -r '.agent_id' ~/.openclaw/openclaw.json ``` - Adapt the JSON path to the actual documented schema and fail if the selected field is absent or is not a string. - Do not place the complete configuration file into prompts, logs, examples, or diagnostic output. - Ensure the configuration file has restrictive filesystem permissions, such as owner-only read and write access where operationally appropriate. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:22
Finding
Third-Party Python Dependencies Are Installed Without Version or Integrity Pinning<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:22-25` **Vulnerability Type**: Unpinned and integrity-unverified dependency installation **Risk Level**: Medium ### Vulnerable Code ```markdown #### 파이썬 패키지 설치 ``` pip install paho-mqtt typer ``` ``` ### Technical Analysis The installation instructions request the latest package versions resolved under the names `paho-mqtt` and `typer`. No exact versions, cryptographic hashes, lockfile, package-index restriction, or isolated environment are specified. Consequently, the code reviewed during an audit may not be the code installed later. A compromised upstream release, compromised package-index account, unsafe index configuration, or incompatible future release could alter installation or runtime behavior. The package names in this project are legitimate and no malicious dependency was identified during this static review; the finding concerns the unsafe installation process. ### Attack Path 1. A user follows the documented `pip install` command. 2. `pip` resolves mutable package versions using its configured indexes. 3. An attacker compromises an upstream distribution channel or causes an unsafe configured index to supply an unintended distribution. 4. The package is installed without a hash mismatch or lockfile preventing the substitution. 5. Malicious package installation or import-time code runs with the permissions of the user performing the installation. ### Impact Assessment A successful supply-chain compromise could execute code with the installing user's privileges. This could expose files and credentials accessible to that account, alter its Python environment, or perform network operations. The reviewed project itself does not demonstrate such a compromise; the risk arises because dependency identity and content are not reproducibly constrained. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Pin reviewed dependency versions in a requirements or lock file. - Include cryptographic hashes and install with hash verification, for example: ```bash python -m pip install --require-hashes -r requirements.txt ``` - Generate the locked requirements from a trusted package index and review transitive dependencies. - Install dependencies in a dedicated virtual environment rather than a shared or privileged interpreter. - Explicitly configure the trusted package index and avoid untrusted supplementary indexes. - Add automated dependency vulnerability and provenance scanning to the release process. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/publish.py:8
Finding
MQTT Agent Metadata Is Exchanged Without Client Authentication or Transport Confidentiality<![CDATA[ ## Vulnerability Details **File Locations**: `scripts/publish.py:8-28` and `scripts/subscribe.py:9-13, 43-51` **Vulnerability Type**: Unauthenticated plaintext MQTT communication with retained messages **Risk Level**: Medium ### Vulnerable Code From `scripts/publish.py`: ```python # 🔒 고정 MQTT 설정 BROKER = "localhost" PORT = 1883 QOS = 1 RETAIN = True def now_ts() -> int: return int(time.time()) def publish_message(topic: str, payload: dict): publish.single( topic=topic, payload=json.dumps(payload), hostname=BROKER, port=PORT, qos=QOS, retain=RETAIN, ) typer.echo(f"Published to {topic}") typer.echo(json.dumps(payload, indent=2)) ``` From `scripts/subscribe.py`: ```python # 🔒 고정 MQTT 설정 BROKER = "localhost" PORT = 1883 KEEPALIVE = 30 QOS = 1 ``` ```python client = mqtt.Client(client_id=f"sub-{kind}", clean_session=True) client.on_connect = on_connect client.on_message = on_message client.connect(BROKER, PORT, keepalive=KEEPALIVE) ``` ### Technical Analysis Both clients connect to the conventional plaintext MQTT port and configure neither TLS nor MQTT credentials. The publisher also sets `retain=True`, causing the broker to preserve the latest agent introduction or status message for future subscribers. The broker is fixed to `localhost`, which limits direct exposure compared with a remote broker. However, the scripts do not require broker authentication, topic authorization, or publisher identity verification. If the local broker permits anonymous access, any other local process able to connect to it may subscribe to agent topics, publish forged messages, or replace retained records. Transport confidentiality is especially relevant if broker configuration, container networking, forwarding, or deployment changes make the endpoint reachable beyond a strictly trusted host. The scripts themselves provide no defense against such changes. ### Attack Path 1. ...[truncated 1142 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require MQTT client authentication using per-agent credentials or client certificates. - Configure broker-side topic ACLs so each publisher can write only to its own topics and subscribers can read only authorized topics. - Enable TLS with certificate validation whenever traffic may cross a trust boundary. - Do not silently fall back to unauthenticated plaintext connections. - Make broker address and security settings explicit configuration values with secure defaults. - Disable retention for transient activity messages unless durable state is required. - Apply an appropriate retained-message expiration policy where supported. - Validate message schemas and add cryptographic publisher identity or signatures if consumers need to trust the claimed `agent_id`. - Document a hardened broker configuration rather than relying on unspecified local broker defaults. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/publish.py:36
Finding
Unvalidated Agent Identifiers Can Alter MQTT Topic Routing Semantics<![CDATA[ ## Vulnerability Details **File Locations**: `scripts/publish.py:36-69` and `scripts/subscribe.py:19-20, 75-101` **Vulnerability Type**: MQTT topic and subscription-filter injection **Risk Level**: Medium ### Vulnerable Code From `scripts/publish.py`: ```python @app.command() def intro( agent_id: str = typer.Option(..., "--agent-id", "-i"), role: str = typer.Option(..., "--role", "-r"), ): """ Publish agent introduction. Topic: agents/{agent_id}/intro """ topic = f"agents/{agent_id}/intro" payload = { "agent_id": agent_id, "role": role, "channel": dedent(f""" You can speak to me directly using the following command. ```bash openclaw --agent {agent_id} --message "message_here" ``` """).strip(), "created_at": now_ts(), } publish_message(topic, payload) @app.command() def status( agent_id: str = typer.Option(..., "--agent-id", "-i"), activity: str = typer.Option(..., "--activity", "-a"), ): """ Publish agent status. Topic: agents/{agent_id}/status """ topic = f"agents/{agent_id}/status" payload = { "agent_id": agent_id, "activity": activity, "ts": now_ts(), } publish_message(topic, payload) ``` From `scripts/subscribe.py`: ```python def _topic(kind: str, agent_id: str | None) -> str: return f"agents/{agent_id}/{kind}" if agent_id else f"agents/+/{kind}" ``` ```python @app.command() def intro( agent_id: str = typer.Option( None, "--agent-id", "-i", help="If provided: agents/<agent_id>/intro. Otherwise: agents/+/intro", ), wait: float = typer.Option( 0.0, "--wait", "-w", help="Seconds to keep listening after subscribe (default: 0, one-shot).", ), ): """ Subscribe and print intro messages, then exit. """ _run_subscribe("intro", agent_id, wait) @app.command ...[truncated 2514 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Validate `agent_id` before using it in either a publication topic or subscription filter. - Use a conservative allowlist suitable for literal identifiers, for example: ```python import re _AGENT_ID = re.compile(r"^[A-Za-z0-9_-]{1,64}$") def validate_agent_id(value: str) -> str: if not _AGENT_ID.fullmatch(value): raise typer.BadParameter( "agent_id must contain only letters, digits, underscores, or hyphens" ) return value ``` - Explicitly reject `/`, `+`, `#`, null characters, control characters, empty values, and excessive lengths. - Keep the intentional all-agent subscription as a separate explicit command or option rather than deriving wildcard behavior from identifier input. - Apply broker ACLs as defense in depth so a malformed filter cannot expand beyond the client's authorized namespace. - Add tests covering wildcard characters, nested topic separators, Unicode control characters, empty identifiers, and maximum lengths. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
설명은 에이전트의 Intro/Status 메시지를 '발행하고 구독'하는 기능이라고 했지만, 제공된 코드는 paho.mqtt.publish를 사용해 두 종류의 메시지를 MQTT로 발행하는 CLI만 구현한다. 구독 로직이나 MQTT 수신 처리는 전혀 없다. 또한 intro payload에 MQTT와 별개로 openclaw 명령을 통한 직접 통신 방법을 안내하는 채널 문자열을 삽입하는 동작이 설명에 명시되어 있지 않다. 주요 목적은 intro/status 발행과 대체로 관련 있지만, 핵심 기능 중 하나로 서술된 구독이 빠져 있으므로 설명과 행동은 정확히 일치하지 않는다.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
설명은 Intro/Status 메시지를 '발행하고 구독'하는 기능 전반을 제공한다고 주장하지만, 제공된 코드 청크는 subscribe.py로서 MQTT 브로커(localhost:1883)에 접속하여 intro/status 토픽을 구독하고 수신 메시지를 출력하는 기능만 구현한다. publish 호출이나 메시지 송신 로직은 전혀 없다. 따라서 설명이 실제 동작보다 넓고, 특히 핵심 capability인 발행 기능이 부재하므로 설명과 코드 사이에 중요한 불일치가 있다. 다만 MQTT를 사용해 Intro/Status 메시지를 다룬다는 큰 범주는 일부 부합한다.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill explicitly instructs users to publish agent identifiers, roles, and live activity updates over MQTT, but provides no warning about metadata exposure, broker access control, retention, or plaintext transport. In a multi-agent environment, this can leak sensitive operational details to anyone with broker access and enable tracking, profiling, or targeting of agents.

Unbounded Resource Access

Medium
Category
Excessive Agency
Content
# 1) connect + subscribe 완료될 때까지 잠깐 돌림 (최대 2초)
    deadline_connect = time.time() + 2.0
    while not connected.is_set() and time.time() < deadline_connect:
        client.loop(timeout=0.1)

    if not connected.is_set():
        print("Failed to connect/subscribe within 2 seconds.")
Confidence
75% confidence
Finding
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Unbounded Resource Access

Medium
Category
Excessive Agency
Content
# 1) connect + subscribe 완료될 때까지 잠깐 돌림 (최대 2초)
    deadline_connect = time.time() + 2.0
    while not connected.is_set() and time.time() < deadline_connect:
        client.loop(timeout=0.1)

    if not connected.is_set():
        print("Failed to connect/subscribe within 2 seconds.")
Confidence
75% confidence
Finding
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The comment `# 🔒 고정 MQTT 설정` is written only in Korean, which introduces a language-specific constraint in the skill file without offering any user choice or documenting a justified locale requirement. This can violate organizational language/locale policy when skills are expected to be accessible or neutral by default.

Static analysis

No suspicious patterns detected.