T03 · Remote Payload Retrieval and Execution
Error
- Location
- scripts/bitcoin_mcp_setup.py:36
- Finding
- Unpinned Remote Package Retrieval and Execution Through uvx## Vulnerability Details **File Location**: `scripts/bitcoin_mcp_setup.py:36-50` (also documented in `SKILL.md:28-51`) **Vulnerability Type**: Unpinned third-party package download and execution **Risk Level**: High ### Vulnerable Code ```python def check_bitcoin_mcp() -> bool: try: result = subprocess.run( ["uvx", "bitcoin-mcp", "--version"], capture_output=True, text=True, timeout=15 ) return result.returncode == 0 except Exception: return False def main(): args = sys.argv[1:] if not args or args[0] == "status": uvx_ok = check_uvx() mcp_ok = check_bitcoin_mcp() if uvx_ok else False ``` The same unsafe execution model is recommended in `SKILL.md`: ```json "mcpServers": { "bitcoin": { "command": "uvx", "args": ["bitcoin-mcp"] } } ``` ### Technical Analysis The helper invokes `uvx bitcoin-mcp --version` without specifying an audited package version, lock file, artifact hash, or trusted immutable source. If the package is not locally available, `uvx` can resolve and download it from the configured Python package index before executing its entry point. Consequently, the effective code executed by this Skill can change after the Skill itself has been reviewed. Invoking `--version` does not provide a security boundary: package initialization, console entry-point code, and imported modules can execute arbitrary Python code before or while processing that option. This behavior also occurs through the default and `status` paths. A command presented as a status check can therefore perform network retrieval and execute newly downloaded third-party code. The documented MCP configuration has the same issue whenever the server is started. ### Attack Path 1. An attacker compromises the `bitcoin-mcp` publishing account, a future package release, one of its transitive dependencies, or the package i ...[truncated 1470 chars]
- Remediation
- ## Remediation Suggestions 1. Pin `bitcoin-mcp` to an exact, audited version in both the Python helper and every documented MCP configuration, rather than resolving the latest available release. 2. Use a lock file that fixes all transitive dependency versions and verifies downloaded artifacts with cryptographic hashes. 3. Prefer installation from a trusted immutable artifact or revision whose integrity is verified before execution. 4. Separate installation from status checking. A `status` command should inspect local package metadata or the local executable without causing package resolution, network access, installation, or entry-point execution. 5. Require an explicit user-approved installation step and clearly disclose that it downloads and executes third-party code. 6. Execute the MCP server with least privilege in an isolated environment or container, with only the required filesystem and network access. 7. Review and monitor the package and its dependency chain before updating the pinned version. Updates should occur through an explicit, auditable process rather than automatically at runtime.
