Back to skill

Security audit

M5Stack Firmware Query

Security checks for vulnerabilities and agentic risk

Overview

This is a read-only public firmware lookup skill, with a configurable API endpoint that users should leave on the trusted default unless intentionally testing.

Install this only if you are comfortable with firmware searches being sent to the public M5Burner service. Keep the API base URL at the default unless you intentionally control and trust another HTTPS-compatible deployment, do not provide bearer tokens or account credentials, and treat firmware descriptions, comments, and source URLs as public third-party content.

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

Warning
Location
scripts/m5stack_firmware_query.py:107
Finding
Unrestricted API Base URL Enables Server-Side Request Forgery and Insecure HTTP Communication<![CDATA[ ## Vulnerability Details **File Location**: `scripts/m5stack_firmware_query.py:107-133` **Additional Locations**: `scripts/m5stack_firmware_query.py:19-21, 1393-1397`; `SKILL.md:13`; `references/api.md:13` **Vulnerability Type**: Unrestricted outbound request destination and cleartext HTTP support **Risk Level**: Medium ### Vulnerable Code ```python DEFAULT_BASE_URL = os.environ.get( "M5BURNER_API_BASE_URL", "https://burner.m5stack.com" ).rstrip("/") ``` ```python class FirmwareApi: def __init__(self, base_url: str, timeout: int) -> None: base_url = base_url.strip().rstrip("/") if not base_url.startswith(("http://", "https://")): raise ApiError("base URL must start with http:// or https://") self.base_url = base_url self.timeout = timeout def get( self, path: str, *, params: Mapping[str, Any] | None = None, headers: Mapping[str, str] | None = None, ) -> Any: query = urlencode(compact_params(params or {})) url = f"{self.base_url}/{path.lstrip('/')}" if query: url = f"{url}?{query}" request_headers = { "Accept": "application/json", "User-Agent": USER_AGENT, } request_headers.update(headers or {}) request = Request(url, headers=request_headers, method="GET") try: with urlopen(request, timeout=self.timeout) as response: raw = response.read() status = response.status ``` ```python parser.add_argument( "--base-url", default=DEFAULT_BASE_URL, help="Compatible M5Burner base URL (or M5BURNER_API_BASE_URL)", ) ``` ### Technical Analysis The API client validates only that the supplied base URL begins with `http://` or `https://`. It does not restrict the destination hostname, port, resolved IP address, or transport security. Consequently, either the `--base-url` argument or the `M5BURNER_API_BASE_URL` ...[truncated 3093 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Enforce the production origin by default** - Permit only `https://burner.m5stack.com` during normal operation. - Compare parsed, normalized scheme, hostname, and port rather than using a string prefix check. 2. **Require HTTPS** - Reject `http://` endpoints outside an explicitly enabled local-test mode. - Do not permit transport downgrades from HTTPS to HTTP. 3. **Separate test configuration from production configuration** - Replace unrestricted `--base-url` behavior with an explicit option such as `--allow-test-endpoint`. - Require deliberate operator approval before connecting to a non-production origin. - Avoid allowing an ambient environment variable to silently redirect production requests. 4. **Block sensitive network destinations** - Resolve the destination hostname and reject loopback, private, link-local, multicast, unspecified, and reserved addresses. - Apply the check to every resolved address to reduce DNS rebinding risk. - Re-resolve and revalidate as close as possible to connection establishment. 5. **Control redirects** - Disable automatic redirects where they are unnecessary. - Otherwise, validate the scheme, hostname, port, and resolved address of every redirect target. - Reject cross-origin redirects and HTTPS-to-HTTP redirects. 6. **Treat API content as untrusted** - Clearly delimit firmware descriptions, comments, developer text, and source URLs as external data. - Ensure downstream agents do not interpret returned catalog text as instructions. - Validate response size and expected schema before processing. 7. **Add security tests** - Confirm rejection of loopback, private, link-local, and reserved destinations. - Confirm rejection of cleartext HTTP in production mode. - Confirm cross-origin and downgrade redirects are rejected. - Confirm the official HTTPS endpoint remains functional. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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
Findings (7)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill instructs the agent to run a local Python script that can access both network resources and environment variables, but the manifest does not declare any explicit tool scope such as allowed tools, network access, or environment exposure limits. That creates an over-privilege/visibility gap: a runtime may grant broader capabilities than intended, making it harder to enforce read-only behavior or prevent accidental access to sensitive environment data or non-public endpoints.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The skill enables implicit invocation without any visible activation constraints, exclusions, or narrowing conditions. Even though the skill is read-only and limited to public firmware discovery, broad automatic triggering can cause the agent to invoke the skill in unintended contexts, potentially leaking user intent to an external repository query path or producing irrelevant/unexpected actions.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This is a code file, so SQP-3 applies to natural-language strings in the code. Several user-visible errors and status messages are emitted only in Chinese (for example at L0088, and similarly later), while the CLI does not offer a corresponding output-language opt-in, which can violate language/locale policy requiring user choice or justified locale constraints.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The code returns multiple user-facing messages such as "不支持的查询意图" and later success/status strings like "意图查询成功" and "聚合查询成功". Because the tool mixes English CLI help with Chinese runtime output and does not let the user choose the output language, this is a clear natural-language locale policy concern rather than a functional bug.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This test asserts that recommendation and classification text contains Chinese strings such as "音乐", "只提到项目由", and "需要配置 Gemini API Key". In a code file, these embedded expectations indicate the skill produces a fixed locale in user-facing text, but there is no evidence here of user opt-in or a documented language-selection mechanism.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The short description is in Chinese while the default prompt is in English, but the manifest does not state whether the user can choose a preferred language or whether the skill is intended for a specific locale. This may create an implicit language policy mismatch without clear user opt-in.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The example response bodies use the Chinese message string "查询成功" in a general API reference, which can be read as prescribing a specific language/locale for responses. The file does not indicate that this is merely an observed production example, offer alternatives, or justify a locale-specific constraint.

Static analysis

No suspicious patterns detected.