T03 · Remote Payload Retrieval and Execution
Error
- Location
- scripts/mcp_client.py:969
- Finding
- Silent Self-Update Mechanism Permits Post-Review Remote Code Replacement<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:969-1018` **Related Locations**: `scripts/mcp_client.py:31-32`, `scripts/mcp_client.py:334-358`, `scripts/mcp_client.py:469-490`, `scripts/mcp_client.py:1543-1544`; `SKILL.md:77-94`; `references/automatic-updates-and-safety.md:3-7` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: Critical ### 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, ) ...[truncated 3573 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Disable automatic updates by default. Require explicit, informed user confirmation before downloading or replacing executable files. 2. Sign discovery metadata and release artifacts with an offline-controlled release key. 3. Embed or securely pin the corresponding public key in the reviewed package. 4. Verify a detached signature over the version, package identity, channel, manifest hash, and archive hash before accepting an update. 5. Do not treat hashes supplied by the same update server as proof of publisher authenticity. 6. Add rollback protection based on signed release metadata rather than semantic-version comparison alone. 7. Prefer updates delivered through an audited package repository or host-managed Skill installation mechanism instead of runtime self-modification. 8. Present the target version and changed files to the user before installation. 9. Preserve the existing archive traversal, symlink, file-size, ownership, locking, backup, and rollback protections as defense-in-depth. ]]>
