T03 · Remote Payload Retrieval and Execution
Error
- Location
- scripts/mcp_client.py:969
- Finding
- Default-Enabled Silent Remote Replacement of Executable Skill Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:969-1023`, `scripts/mcp_client.py:1537-1539`; behavior is disclosed in `SKILL.md:183-203` and `references/automatic-updates-and-safety.md:3-19` **Vulnerability Type**: Silent remote code update channel **Risk Level**: High ### Vulnerable Code ```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 _ensure_owned_baseline( install_root=resolved_root, update_home=update_home, get_bytes=get_bytes, ) discovery = checked["discovery"] manifest, new_files = download_update(discovery, get ...[truncated 3151 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Disable automatic installation by default. Update checks may be automatic, but replacement must require explicit, informed user approval. 2. Display the current version, proposed version, release identity, and changed file list before installation. 3. Sign release manifests with a dedicated offline signing key and pin the corresponding public key in the audited client. 4. Verify signatures independently of the HTTPS/CDN trust domain; checksums supplied by the same release channel are insufficient as an independent authorization mechanism. 5. Require a fresh audit or trust decision before executing a changed `SKILL.md` or any changed script. 6. Separate update functionality from the credential-bearing MCP client so an updater does not need access to account credentials. 7. Preserve rollback and path-validation controls, as those controls correctly reduce archive traversal and partial-update risks. ]]>
