Back to skill

Security audit

ST200TH 温湿度变送器

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent ST200TH device-management tool, but it gives broad remote control over devices through weakly protected MQTT and unsafe firmware/reset workflows.

Review carefully before installing. Use only on isolated, trusted networks and only for devices you own or administer. Treat reset, restart, compensation, custom configuration, and OTA as live device changes; confirm the exact MAC and avoid OTA firmware unless you can independently verify the firmware source and integrity.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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)

T09 · Insecure Skill Coding Practices

Error
Location
st200th_mqtt.py:38
Finding

Shared Credentials and Plaintext MQTT Allow Unauthorized Device Control

Content
View full analysis
/publish /public//subscribe ``` No command signature, per-device secret, nonce validation, or application-level authorization is implemented. The exposed command interface includes configuration changes, reboot, factory reset, and OTA upgrade. ### Attack Path 1. The attacker downloads or inspects the skill package and obtains the embedded ...[truncated 1426 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
st200th_mqtt.py:274
Finding

OTA Upgrade Accepts an Unverified Plaintext Firmware Location

Content
View full analysis
dict: """ OTA firmware upgrade (immediate, no response). Args: uri: Firmware download address (maximum 128 characters, HTTP only) """ if len(uri) > 128: return {"success": False, "error": f"URI too long: {len(uri)} characters (maximum 128)", "data": None} request = { "id": str(uuid.uuid4()).upper(), "param": { "type": "ota", "uri": uri } } return mqtt_send(mac, request, wait_response=False) ``` The project documentation explicitly states that OTA supports HTTP and does not support HTTPS: ```text URI only supports HTTP (HTTPS is not supported) URI maximum length: 128 characters ``` ### Technical Analysis The function validates only the string length before instructing the device to retrieve and install firmware. It does not: - Parse and validate the URI scheme. - Require an authenticated transport. - Restrict downloads to approved hosts. - Require an expected firmware digest. - Verify a digital signature or trusted signing key. - Validate firmware model, version, or rollback policy. The documented HTTP-only transport provides no server authentication or integrity protection. A network attacker can substitute the firmware response even when the operator supplied a legitimate URI. An attacker with access to the MQTT command channel can instead provide an attacker-controlled URI directly. Although the Python process does not itself download or execute the payload, it directs the managed device to retrieve and execute firmware whose contents can change after this skill has been reviewed. ### Attack Path 1. The attacker obtains MQTT command-channe ...[truncated 1329 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
st200th_mqtt.py:634
Finding

Destructive Reset and OTA Operations Lack Code-Level Confirmation

Content
View full analysis
dict: """Restore factory settings (immediate, no response).""" request = { "messageid": "", "param": {"type": "reset"} } return mqtt_send(mac, request, wait_response=False) ``` ```python # reset: restore factory settings p_rs = sub.add_parser("reset", help="Restore factory settings (immediate; use caution)") p_rs.add_argument("--mac", help="Specify device MAC") # ota: firmware upgrade p_ota = sub.add_parser("ota", help="OTA firmware upgrade (immediate)") p_ota.add_argument("--mac", help="Specify device MAC") p_ota.add_argument("--uri", required=True, help="Firmware download address (HTTP, maximum 128 characters)") ``` ```python elif args.subcmd == "reset": macs = resolve_mac(args.mac) if isinstance(macs, dict): print(json.dumps(macs, ensure_ascii=False)) sys.exit(1) mac = macs[0] r = cmd_reset(mac) name = devices.get(mac, {}).get("name", mac) print(f"[{name}] {'Factory-reset command sent' if r['success'] else 'Error: ' + r['error']}") elif args.subcmd == "ota": macs = resolve_mac(args.mac) if isinstance(macs, dict): print(json.dumps(macs, ensure_ascii=False)) sys.exit(1) mac = macs[0] r = cmd_ota(mac, args.uri) name = devices.get(mac, {}).get("name", mac) print(f"[{name}] {'OTA command sent, firmware: ' + args.uri if r['success'] else 'Error: ' + r['error']}") ``` ### Technical Analysis `SKILL.md` instructs the AI agent to obtain user confirmation before reset and OTA operations. That control exists only as natural-language guidance and is not enforced by the executable interface. The CLI does not require a confirmation flag, interactive acknowledgement, device-name re-entry, approval token, or equi ...[truncated 1568 chars]
Remediation
View remediation
` or `--yes-i-understand` for non-interactive use. 2. Default to an interactive confirmation that displays the resolved device name, full MAC, operation, and consequences. 3. For OTA, display the normalized firmware origin and expected digest before approval. 4. Consider requiring the user to re-enter the target MAC or device name for factory reset. 5. Reject destructive commands when standard input is non-interactive unless a narrowly scoped approval token is supplied. 6. Make approval tokens short-lived, operation-specific, and device-specific. 7. Add an optional dry-run mode that prints the exact target and MQTT request without publishing it. 8. Record an audit log containing the target, operation, requester, time, and result without logging secrets. 9. Retain the agent-level confirmation instruction as defense in depth, but do not rely on documentation as the sole control. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Unpinned Dependencies Permit Unreviewed Future Package Versions

Content
View full analysis
=2.0.0 ``` Related installation examples also resolve mutable versions: ```bash npx clawhub@latest install st200th-mqtt pip3 install "paho-mqtt>=2.0.0" ``` The skill installation metadata specifies the package without a fixed version: ```yaml install: - kind: uv package: paho-mqtt bins: [] ``` ### Technical Analysis The lower-bound-only requirement permits installation of any current or future `paho-mqtt` release. The `@latest` installer reference similarly permits the selected installer implementation to change over time. No dependency lockfile, artifact hash, or integrity constraint is present. As a result, two installations of the same audited project may execute different third-party code. A future compromised, malicious, or incompatible upstream release could be installed automatically without changes to this repository and without being covered by the current audit. No evidence was found that `paho-mqtt` is currently malicious; the risk arises from unconstrained future dependency resolution and lack of reproducible integrity controls. ### Attack Path 1. A dependency release or distribution account is compromised, or a future release introduces a security vulnerability. 2. A user installs the project using the provided requirement or skill metadata. 3. The package manager resolves the newest version satisfying `>=2.0.0`, rather than a previously reviewed version. 4. The newly resolved package is installed and imported by `st200th_mqtt.py`. 5. Any malicious import-time or runtime behavior executes with the privileges of the user running the skill. For the documented `npx ...@latest` command, compromise of a newly selected installer version can similarly affe ...[truncated 501 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (10)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README advertises reset, restart, configuration changes, and calibration actions without prominently warning that they are state-changing and can erase configuration, interrupt monitoring, or push unsafe settings to live devices. In an agent-skill context, vague destructive commands are more dangerous because an AI or operator may execute them with incomplete awareness of operational consequences across one or many devices.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README documents OTA firmware updates and HTTP-based device communication over plaintext HTTP, including an explicit note that HTTPS is unsupported, but provides no warning about tampering, interception, or credential/privacy exposure. For an IoT management skill, this is especially dangerous because firmware or configuration fetched over HTTP can be modified by an on-path attacker, potentially leading to device compromise at scale.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill invokes a local Python script and explicitly maintains device state via commands like add/list/remove, which implies filesystem access, yet the manifest declares no permissions or allowed-tools scope. Missing scope boundaries weakens least-privilege controls and can let the skill read or modify local files without transparent review, especially if the backing script behavior changes or is broader than documented.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The documentation permits applying compensation changes to all saved devices with --all, but does not require a warning or confirmation for this bulk action. In this skill’s context, compensation directly alters sensor readings, so a mistaken bulk change can silently corrupt environmental telemetry across multiple devices and downstream automations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The restart command is described as immediate and without response, but unlike reset and ota it does not require an explicit confirmation workflow. A restart can interrupt monitoring, temporarily blind downstream systems, or apply pending configuration changes unexpectedly, making accidental or ambiguous invocation operationally risky in an IoT management context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The reset subcommand sends a factory-reset command immediately after argument parsing with no confirmation prompt, dry-run mode, or explicit force flag. In an agent skill context, this is dangerous because a mistaken invocation, prompt-injection-driven tool use, or ambiguous device selection can irreversibly wipe configuration and disrupt operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The OTA command accepts a user-supplied firmware URI and sends the upgrade command immediately without confirmation, provenance checks, or integrity validation. In this device-management skill, that creates a meaningful path to bricking devices or installing untrusted firmware if the command is invoked accidentally or by a compromised workflow.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is only lower-bounded (paho-mqtt>=2.0.0), so installs are not reproducible and may pull in newer major or minor releases with breaking changes or newly introduced vulnerabilities. In a skill that manages MQTT-connected industrial/environmental devices and supports configuration changes, OTA, and reboot actions, an unexpected dependency version can increase supply-chain and reliability risk even if this file alone does not prove active compromise.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
paho-mqtt>=2.0.0

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The restart command is dispatched immediately with no confirmation or warning, which can cause avoidable service interruption if triggered accidentally. While restart is less destructive than reset or OTA, in an automation/agent setting the lack of friction increases the chance of unintended operational impact.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.