T03 · Remote Payload Retrieval and Execution
Error
- Location
- scripts/mcp_client.py:957
- Finding
- Silent Self-Update Allows Remote Replacement of Executable Skill Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:957-1019`, with update endpoints defined at `scripts/mcp_client.py:31-32` and automatic invocation at `scripts/mcp_client.py:1535-1537` **Vulnerability Type**: Remote payload retrieval and execution without an independent publisher trust anchor **Risk Level**: High ### Vulnerable Code ```python PACKAGE_DISCOVERY_URL = "https://beatra.ai/skills/homeroom-week-voice/channels/clawhub/install.json" PACKAGE_CDN_BASE_TEMPLATE = "https://cdn.beatra.ai/agent-packages/homeroom-week-voice/channels/clawhub/v{version}" ``` ```python def maybe_auto_update( *, state_dir: Path | None = None, install_root: Path | None = None, get_bytes: GetBytes = _default_get_bytes, now: float | None = None, ) -> bool: """Best-effort silent update. Never block the requested MCP command.""" resolved_state = state_dir or Path.home() / ".beatra" try: resolved_root = (install_root or _current_install_root()).resolve() update_home = _update_home(resolved_state, resolved_root) observed_at = time.time() if now is None else now nonce = _lock_update(update_home, now=observed_at) if nonce is None: return False try: recover_update(state_dir=resolved_state, install_root=resolved_root) state = _read_update_state(update_home) if state.get("auto_update", True) is False: return False last_checked = state.get("last_checked_at") if ( isinstance(last_checked, (int, float)) and observed_at - float(last_checked) < UPDATE_CHECK_MAX_AGE_SECONDS ): return False state["last_checked_at"] = observed_at _write_private_json(update_home / "state.json", state) checked = check_update(get_bytes=get_bytes) if not checked["update_available"]: return False ...[truncated 3232 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Disable automatic installation by default. Update checks may remain opt-in or informational, but executable replacement should require informed user confirmation. 2. Sign discovery metadata or release manifests using a dedicated offline publisher key. 3. Embed or securely provision the corresponding public verification key in the audited client. 4. Verify a detached signature before accepting the manifest, archive hash, version, or file list. 5. Consider a signed metadata framework such as TUF to provide key rotation, rollback protection, threshold signatures, and repository-compromise resilience. 6. Display the current version, proposed version, release identity, and changed executable files before installation. 7. Preserve the existing archive limits, path validation, ownership restrictions, lock, rollback journal, and downgrade protection as defense-in-depth. 8. Ensure update failures are observable through an audit log rather than being completely suppressed, while still preventing automatic replay of paid calls. ]]>
