Back to skill

Security audit

bitcoin-mcp

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a Bitcoin MCP connector, but it runs an unpinned third-party package and relies on an external API, so users should review it before installing.

Install only if you are comfortable running the current PyPI bitcoin-mcp package under your user account and sending Bitcoin lookup metadata to the Satoshi API. Prefer a pinned, reviewed package version or isolated environment, and avoid submitting sensitive wallet, transaction, or PSBT data unless that third-party exposure is acceptable.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/bitcoin_mcp_setup.py:36
Finding

Unpinned Remote Package Retrieval and Execution Through uvx

Content
View full analysis

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
View 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.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description promises a functional Bitcoin tool suite/MCP server with many capabilities like mempool analysis, address lookups, and transaction decoding. The supplied code chunk does not provide any of those behaviors. Instead, it is a helper utility for setup and status checking: it verifies whether uvx is installed, runs bitcoin-mcp --version, prints configuration JSON, and shows links. While this script is related to the Bitcoin MCP project, its actual behavior is materially different from the declared purpose of the skill itself, so this is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill invokes an MCP server via the shell (uvx bitcoin-mcp) but does not declare any explicit tool scope or permissions boundaries. That increases the risk that an agent or user enables shell-capable behavior without clear review, making execution of external code less transparent and weakening least-privilege controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill states it is backed by the Satoshi API but does not clearly warn users that wallet addresses, transaction identifiers, PSBT-related details, and other blockchain queries may be sent to a third-party service. In a Bitcoin-analysis context, this is privacy-sensitive metadata that can reveal user interests, holdings, counterparties, or operational patterns even if no private keys are transmitted.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

Using uvx bitcoin-mcp without a pinned version causes the latest package version to be fetched and executed at runtime, creating a supply-chain risk. If the package is compromised upstream or a breaking/malicious release is published, users may unknowingly execute unreviewed code on their systems.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/bitcoin_mcp_setup.py (reported line 40)May include surrounding context.

python
def check_bitcoin_mcp() -> bool:
    try:
        result = subprocess.run(
            ["uvx", "bitcoin-mcp", "--version"],
            capture_output=True, text=True, timeout=15
        )

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding

The helper instructs users to run 'uvx bitcoin-mcp' without pinning a specific version, and uvx may download/execute the latest package on first use. In an agent-skill context, this increases supply-chain risk: a compromised upstream release or typosquatted package could lead to arbitrary code execution when users test or enable the MCP server.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/bitcoin_mcp_setup.py (reported line 73)May include surrounding context.

python
print("✗ uvx not found. Install uv: https://github.com/astral-sh/uv")
            sys.exit(1)
        try:
            result = subprocess.run(
                ["uvx", "bitcoin-mcp", "--version"],
                capture_output=True, text=True, timeout=20
            )