Back to skill

Security audit

ClawRTC

Security checks for vulnerabilities and agentic risk

Overview

This is a real mining and wallet skill, but its code contradicts its privacy and TLS promises in ways users should review before installing.

Install only if you intentionally want to run a crypto miner and are comfortable with wallet-linked hardware fingerprinting. Before using it, review the plaintext miner endpoint, hidden install telemetry, MAC/hostname collection, cloud metadata probes, optional auto-start service, and BCOS admin-key path. Avoid running it on cloud hosts or machines with sensitive credentials, and do not use BCOS certification/admin keys until TLS verification and disclosure issues are fixed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (7)

other

Warning
Location
clawrtc/cli.py:320
Finding
Undisclosed third-party installation telemetry contradicts the privacy disclosure<![CDATA[ ## Vulnerability Details **File Location**: `clawrtc/cli.py:320-337` **Vulnerability Type**: Undisclosed telemetry and privacy-policy mismatch **Risk Level**: Medium ### Complete Code Snippet ```python # Anonymous install telemetry — non-blocking, fails silently, no PII try: import threading, urllib.request def _ping(): try: payload = json.dumps({ "package": "clawrtc", "version": __version__, "platform": platform.system(), "arch": platform.machine(), "source": "pip" }).encode() req = urllib.request.Request( "https://bottube.ai/api/telemetry/install", data=payload, headers={"Content-Type": "application/json"} ) urllib.request.urlopen(req, timeout=5) except Exception: pass threading.Thread(target=_ping, daemon=True).start() except Exception: pass ``` ### Technical Analysis After installation, the package starts a background thread that sends the package version, operating system, processor architecture, and installation source to `bottube.ai`. This destination is separate from the configured RustChain node. The behavior is not disclosed in the installation consent prompt. It also contradicts the statements in `SKILL.md` that there is “No post-install telemetry” and that data is sent only to the RustChain node. Silently suppressing all errors makes this behavior difficult for users to detect or troubleshoot. Although the JSON body does not explicitly contain a credential or wallet private key, the receiving server also obtains ordinary network metadata such as the source IP address and request time. Combined with platform and architecture, this permits installation tracking. ### Attack Path 1. A user installs the package and runs `clawrtc install`. 2. The user approves the displayed consent disclosure, which does not me ...[truncated 633 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove installation telemetry unless it is necessary for the declared mining functionality. 2. If telemetry is retained, make it explicitly opt-in and disabled by default. 3. Add the destination, complete data schema, retention policy, and purpose to both `SKILL.md` and the interactive consent disclosure. 4. Provide a persistent configuration switch such as `--enable-telemetry`. 5. Do not label data as anonymous without considering source IP addresses and correlation metadata. 6. Avoid silently swallowing all errors; provide an auditable local indication when telemetry is enabled and sent. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
clawrtc/data/miner.py:376
Finding
Hostname, MAC addresses, wallet identifiers, and hardware fingerprints are transmitted over plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `clawrtc/data/miner.py:77`, `clawrtc/data/miner.py:376-403`, and `clawrtc/data/miner.py:491-583` **Vulnerability Type**: Plaintext transmission of sensitive device and mining information **Risk Level**: High ### Complete Code Snippet ```python # Configuration RUSTCHAIN_API = "http://50.28.86.131:8088" ``` ```python def _get_hw_info(self): return { "platform": platform.system(), "machine": platform.machine(), "model": platform.machine() or "Windows-PC", "hostname": platform.node(), "family": "Windows", "arch": platform.processor() or "x86_64", "macs": self._get_mac_addresses() } ``` ```python attestation = { "miner": self.wallet_address, "miner_id": self.miner_id, "report": report_payload, "device": { "family": self.hw_info["family"], "arch": self.hw_info["arch"], "model": self.hw_info.get("model") or self.hw_info.get("machine"), "cpu": platform.processor(), "cores": os.cpu_count() }, "signals": { "macs": self.hw_info["macs"], "hostname": self.hw_info["hostname"] } } ``` ```python try: resp = requests.post( f"{self.node_url}/attest/submit", json=attestation, timeout=30 ) if resp.status_code == 200 and resp.json().get("ok"): self.attestation_valid_until = time.time() + 580 self.last_attestation_error = "" return True ``` ### Technical Analysis The installed miner’s default node is a raw IP address using unencrypted HTTP. The attestation submitted to that endpoint contains: - Wallet or miner identifier - Miner ID - Hostname - MAC addresses - CPU model, architecture, and core count - Detailed timing and hardware-fingerprint measurements - VM and cloud-environment indicators - Attestation nonce, commitment, signature, and public key where available The Skill documentation states that Rus ...[truncated 1621 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the raw HTTP endpoint with a stable HTTPS hostname. 2. Require normal certificate-chain and hostname validation for every miner request. 3. Reject plaintext HTTP node URLs unless a clearly labeled development-only override is supplied. 4. Remove MAC addresses and hostnames from attestations unless the server can demonstrate that they are strictly necessary. 5. If host identifiers remain necessary, obtain explicit informed consent and accurately document every transmitted field and destination. 6. Use a privacy-preserving derived identifier instead of raw MAC addresses or hostnames. 7. Fail closed when strong Ed25519 signing is unavailable. 8. Add integration tests that verify all production endpoints use HTTPS and certificate verification. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
clawrtc/cli.py:918
Finding
BCOS certification disables TLS verification while transmitting an administrator credential<![CDATA[ ## Vulnerability Details **File Location**: `clawrtc/cli.py:918-950` **Vulnerability Type**: Credential exposure through disabled certificate and hostname validation **Risk Level**: Critical ### Complete Code Snippet ```python # Read admin key from env or config admin_key = os.environ.get("RC_ADMIN_KEY", "") if not admin_key: config_path = os.path.join(os.path.expanduser("~"), ".clawrtc", "admin_key") if os.path.exists(config_path): with open(config_path) as f: admin_key = f.read().strip() if not admin_key: print(f"{YELLOW}No admin key found. Set RC_ADMIN_KEY env var or create ~/.clawrtc/admin_key{NC}") print(f"{YELLOW}Skipping on-chain anchoring. Report saved locally.{NC}") # Save report locally out_path = os.path.join(path, f"{cert_id}.json") with open(out_path, "w") as f: json.dump(report, f, indent=2) print(f"{GREEN}Report saved: {out_path}{NC}") return try: ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE payload = json.dumps(report).encode() req = urllib.request.Request( f"{NODE_URL}/bcos/attest", data=payload, headers={ "Content-Type": "application/json", "X-Admin-Key": admin_key, }, method="POST", ) with urllib.request.urlopen(req, context=ctx, timeout=30) as resp: data = json.loads(resp.read().decode()) ``` ### Technical Analysis The certification command reads a privileged administrator key from either `RC_ADMIN_KEY` or `~/.clawrtc/admin_key`. It then creates an SSL context but explicitly disables both hostname checking and certificate validation before transmitting the key in the `X-Admin-Key` HTTP header. Encryption without peer authentication does not protect against active interception. Any attacker capable of redirecting or intercepting the connection can present an arbitrary certificate, impersonate the RustChain node, and ...[truncated 1438 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove both of the following assignments: - `ctx.check_hostname = False` - `ctx.verify_mode = ssl.CERT_NONE` 2. Use `ssl.create_default_context()` without weakening its defaults. 3. Fail closed on certificate or hostname validation errors. 4. Consider certificate or public-key pinning for privileged administration requests. 5. Replace long-lived administrator keys with narrowly scoped, short-lived authorization tokens. 6. Ensure the key authorizes only the minimum certification operation required. 7. Store file-based credentials with mode `0600` and reject symlinks or files owned by another user. 8. Add tests using an untrusted certificate and mismatched hostname, and require both connections to fail. 9. Rotate any administrator key previously used through this insecure path. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
clawrtc/data/fingerprint_checks.py:435
Finding
Hardware fingerprinting actively probes the cloud metadata service and requests an AWS IMDSv2 token<![CDATA[ ## Vulnerability Details **File Location**: `clawrtc/data/fingerprint_checks.py:435-464` **Vulnerability Type**: Access to a sensitive cloud metadata trust boundary beyond minimum requirements **Risk Level**: Medium ### Complete Code Snippet ```python # --- Cloud metadata endpoint check --- # AWS, GCP, Azure, DigitalOcean all use 169.254.169.254 try: import urllib.request req = urllib.request.Request( "http://169.254.169.254/", headers={"Metadata": "true"} ) resp = urllib.request.urlopen(req, timeout=1) cloud_body = resp.read(512).decode("utf-8", errors="replace").lower() cloud_provider = "unknown_cloud" if "latest" in cloud_body or "meta-data" in cloud_body: cloud_provider = "aws_or_gcp" if "azure" in cloud_body or "microsoft" in cloud_body: cloud_provider = "azure" vm_indicators.append("cloud_metadata:{}".format(cloud_provider)) except: pass # --- AWS IMDSv2 check (token-based, t3/t4 Nitro instances) --- try: import urllib.request token_req = urllib.request.Request( "http://169.254.169.254/latest/api/token", headers={"X-aws-ec2-metadata-token-ttl-seconds": "5"}, method="PUT" ) token_resp = urllib.request.urlopen(token_req, timeout=1) if token_resp.status == 200: vm_indicators.append("cloud_metadata:aws_imdsv2") except: pass ``` ### Technical Analysis The anti-emulation check directly accesses the link-local cloud metadata address and performs an AWS IMDSv2 token request. The current implementation does not request an IAM credential path and does not read or transmit the returned token. It is therefore not, by itself, confirmed credential theft. Nevertheless, cloud metadata is a sensitive trust boundary. The package already checks DMI values, CPU hypervisor flags, environment variables, `/sys/hypervisor/type`, and `systemd-detect-virt`. Actively requesting an IMDSv2 token is not necessary for ordinary hardware timing ch ...[truncated 1350 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the metadata GET and IMDSv2 token request. 2. Rely on less sensitive indicators already collected, including DMI data, hypervisor flags, and `systemd-detect-virt`. 3. If metadata detection is indispensable, require explicit opt-in through a dedicated option. 4. Document the exact endpoint, methods, headers, purpose, and returned data before consent. 5. Never request metadata credentials, role names, user data, or identity documents. 6. Add egress controls or a narrowly scoped transport abstraction that prevents access to credential-bearing metadata paths. 7. Treat metadata results only as advisory because local services can spoof the endpoint. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
clawrtc/cli.py:747
Finding
RTC wallet exports containing private keys are created without restrictive permissions<![CDATA[ ## Vulnerability Details **File Location**: `clawrtc/cli.py:747-763` **Vulnerability Type**: Insecure storage of wallet private keys **Risk Level**: High ### Complete Code Snippet ```python export_path = getattr(args, "output", None) or f"rtc-wallet-{wallet['address']}.json" # Remove private key from export if --public-only if getattr(args, "public_only", False): export_data = {k: v for k, v in wallet.items() if k != "private_key"} else: export_data = wallet with open(export_path, "w") as f: json.dump(export_data, f, indent=2) print(f"\n {GREEN}Wallet exported to:{NC} {export_path}") if not getattr(args, "public_only", False): print(f" {RED}Contains private key — keep this file secure!{NC}") print() ``` ### Technical Analysis The default export includes the wallet’s Ed25519 private key. Unlike the primary wallet file, which is explicitly changed to mode `0600`, the export is created using the process’s current umask and receives no subsequent permission hardening. On systems with a common `022` umask, the result may be mode `0644`, allowing other local users to read it. A user-supplied output path can also place the private key in a synchronized, indexed, backed-up, or source-controlled directory. Plain `open(..., "w")` additionally follows symbolic links and overwrites an existing destination. ### Attack Path 1. A wallet owner runs `clawrtc wallet export` without `--public-only`. 2. The command writes the complete wallet JSON, including `private_key`. 3. The operating-system umask permits group or world readability, or the selected directory is shared or synchronized. 4. Another local user, process, backup service, or repository consumer obtains the exported file. 5. The attacker reconstructs the Ed25519 private key. 6. The attacker signs valid RTC transfers and spends funds controlled by that wallet. A local attacker who can pre-create the destination as a symbolic link may also redirect the private-key content into anothe ...[truncated 372 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create exports atomically with mode `0600`, for example using `os.open()` with `O_CREAT | O_EXCL | O_WRONLY` and permission `0o600`. 2. Reject symbolic-link destinations and verify the final file is a regular file owned by the current user. 3. Refuse to overwrite existing files unless a separate explicit option is provided. 4. Make `--public-only` the default and require a clearly named option such as `--include-private-key`. 5. Warn when the destination is inside a repository, shared directory, temporary directory, or known synchronization folder. 6. Consider encrypting private-key exports with an authenticated password-based format. 7. Call `os.chmod(export_path, 0o600)` as defense in depth after an atomic secure creation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
clawrtc/cli.py:46
Finding
Standard installation omits strong signing modules and silently falls back to a legacy pseudo-signature<![CDATA[ ## Vulnerability Details **File Location**: `clawrtc/cli.py:46-49`, `clawrtc/cli.py:257-258`, and `clawrtc/data/miner.py:42-69` **Vulnerability Type**: Security feature not deployed by the installer and insecure authentication fallback **Risk Level**: High ### Complete Code Snippet ```python # Bundled files shipped with the package BUNDLED_FILES = [ ("miner.py", "miner.py"), ("fingerprint_checks.py", "fingerprint_checks.py"), ] ``` ```python # Extract bundled miner files (no download!) log("Extracting bundled miner scripts...") for src_name, dest_name in BUNDLED_FILES: src = os.path.join(DATA_DIR, src_name) dest = os.path.join(INSTALL_DIR, dest_name) if not os.path.exists(src): error(f"Bundled file missing: {src_name}. Package may be corrupted.") shutil.copy2(src, dest) ``` ```python try: from miner_crypto import get_or_create_keypair, sign_payload # noqa: F401 CRYPTO_AVAILABLE = True except ImportError: CRYPTO_AVAILABLE = False # Shared pipe-message builder (PR #6839 review) try: from miners.signing_helpers import build_pipe_sign_message _SIGNING_HELPERS = True except ImportError: try: from signing_helpers import build_pipe_sign_message _SIGNING_HELPERS = True except ImportError: _SIGNING_HELPERS = False ``` The resulting fallback is: ```python else: # Legacy fallback — sha512 pseudo-signature. Server accepts but # logs a warning. Real wallet-hijack protection requires PyNaCl. msg = f"{nonce}:{self.miner_id}:{self.wallet_address}:{int(time.time())}" attestation["signature"] = hashlib.sha512(msg.encode()).hexdigest() attestation["signature_type"] = "sha512_legacy" ``` ### Technical Analysis The package contains `miner_crypto.py` and `signing_helpers.py`, but the installation list copies only `miner.py` and `fingerprint_checks.py` into `~/.clawrtc`. The created virtual environment installs `requests`, but does not install PyNaCl, which `mine ...[truncated 1903 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Include `miner_crypto.py` and `signing_helpers.py` in `BUNDLED_FILES`. 2. Install a pinned, supported Ed25519 dependency in the miner virtual environment. 3. Add an installation-time self-test that signs and verifies a challenge using the deployed environment. 4. Fail closed if Ed25519 support cannot be loaded; do not submit attestations using an unkeyed hash. 5. Remove server support for the legacy SHA-512 pseudo-signature after a controlled migration. 6. Ensure the server requires a valid signature over all security-relevant fields, including wallet, miner ID, nonce, commitment, fingerprint, and proof data. 7. Replace self-computed verification output with comparison against a signed release manifest or trusted published checksums. 8. Add packaging tests that install into a clean environment and verify that every required runtime module is present. ]]>

T06 · System Persistence

Note
Location
clawrtc/cli.py:375
Finding
Optional persistent mining services continuously transmit host data after login or reboot<![CDATA[ ## Vulnerability Details **File Location**: `clawrtc/cli.py:375-451` **Vulnerability Type**: Persistent user service with continuous network and hardware-access capabilities **Risk Level**: Low ### Complete Code Snippet ```python def _setup_systemd(wallet): """Set up systemd user service on Linux.""" service_dir = os.path.expanduser("~/.config/systemd/user") os.makedirs(service_dir, exist_ok=True) service_file = os.path.join(service_dir, "clawrtc-miner.service") python_bin = os.path.join(VENV_DIR, "bin", "python") miner_py = os.path.join(INSTALL_DIR, "miner.py") with open(service_file, "w") as f: f.write(textwrap.dedent(f"""\ [Unit] Description=ClawRTC RTC Miner — AI Agent Mining After=network-online.target Wants=network-online.target [Service] ExecStart={python_bin} {miner_py} --wallet {wallet} Restart=always RestartSec=30 WorkingDirectory={INSTALL_DIR} Environment=PYTHONUNBUFFERED=1 [Install] WantedBy=default.target """)) try: run_cmd("systemctl --user daemon-reload") run_cmd("systemctl --user enable clawrtc-miner") run_cmd("systemctl --user start clawrtc-miner") ``` ```python try: run_cmd(f'launchctl unload "{plist_file}" 2>/dev/null', check=False) run_cmd(f'launchctl load "{plist_file}"') success("LaunchAgent installed and loaded (auto-restarts on login)") except Exception: warn("Could not load LaunchAgent. Use: clawrtc start") ``` ### Technical Analysis When the user supplies `--service`, the package creates either a systemd user service or macOS LaunchAgent. Both mechanisms survive the immediate command invocation and automatically restart the miner. The persistence itself is consistent with an explicitly requested background miner and is not covert: installation only calls these functions when `--service` is ...[truncated 1401 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Preserve the current explicit `--service` opt-in requirement. 2. Display a separate confirmation describing automatic startup, restart behavior, data collection, endpoints, and resource use. 3. Do not enable the service until production network transport uses verified HTTPS. 4. Pass an explicit secure node URL in the generated service definition. 5. Provide a dedicated `clawrtc service disable` command in addition to full uninstall. 6. Make service status and the exact executable path easy to inspect. 7. Apply reasonable CPU, memory, restart-rate, and network limits in the service configuration. 8. Ensure upgrades cannot silently replace an existing foreground-only installation with a persistent service. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (100)

Tainted flow: 'req' from os.environ.get (line 941, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
try:
        import urllib.request
        req = urllib.request.Request(f"{NODE_URL}/api/miners")
        with urllib.request.urlopen(req, timeout=10) as resp:
            miners = json.loads(resp.read())
            log(f"Active miners on network: {len(miners)}")
    except Exception:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 941, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
try:
        import urllib.request
        req = urllib.request.Request(f"{NODE_URL}/api/miners")
        with urllib.request.urlopen(req, timeout=10) as resp:
            miners = json.loads(resp.read())
            log(f"Active miners on network: {len(miners)}")
    except Exception:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 941, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
try:
        import urllib.request
        req = urllib.request.Request(f"{NODE_URL}/api/miners")
        with urllib.request.urlopen(req, timeout=10) as resp:
            miners = json.loads(resp.read())
            log(f"Active miners on network: {len(miners)}")
    except Exception:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 941, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
data=payload,
                    headers={"Content-Type": "application/json"}
                )
                urllib.request.urlopen(req, timeout=5)
            except Exception:
                pass
        threading.Thread(target=_ping, daemon=True).start()
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 941, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
ctx.verify_mode = ssl.CERT_NONE

        req = urllib.request.Request(url)
        with urllib.request.urlopen(req, context=ctx, timeout=15) as resp:
            data = json.loads(resp.read().decode())

        if not data.get("ok"):
Confidence
98% confidence
Finding
BCOS verification disables TLS certificate and hostname validation before fetching purported verification data. A man-in-the-middle can spoof the server response and make untrusted certificates appear verified, undermining the security promise of the verification feature.

Tainted flow: 'req' from os.environ.get (line 941, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
},
            method="POST",
        )
        with urllib.request.urlopen(req, context=ctx, timeout=30) as resp:
            data = json.loads(resp.read().decode())

        if data.get("ok"):
Confidence
99% confidence
Finding
This request sends an admin key in the X-Admin-Key header while TLS verification is explicitly disabled. An active network attacker can intercept the key, modify the attestation request, or impersonate the server, leading to credential theft and unauthorized certification actions.

Tainted flow: 'req' from os.environ.get (line 941, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
ctx.check_hostname = False
        ctx.verify_mode = ssl.CERT_NONE

        with urllib.request.urlopen(req, context=ctx, timeout=30) as resp:
            pdf_data = resp.read()

        out_path = os.path.join(path, f"{cert_id}.pdf")
Confidence
94% confidence
Finding
The certificate PDF is downloaded with TLS verification disabled, allowing content spoofing or malicious file substitution. While less severe than admin-key exposure, it can still mislead users or deliver untrusted artifacts presented as official certificates.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
def run_cmd(cmd, check=True, capture=False):
    """Run a shell command."""
    try:
        result = subprocess.run(
            cmd, shell=True, check=check,
            capture_output=capture, text=True
        )
Confidence
99% confidence
Finding
Using subprocess.run with shell=True in a shared helper is a classic unsafe default because future and current callers can pass interpolated strings that the shell will parse. In this file, command strings include quoted paths and generated values, so an attacker controlling environment-derived paths or arguments may achieve command execution.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The consent text explicitly claims data is sent only to the RustChain node, but installation also silently sends telemetry to bottube.ai. Misrepresenting outbound data flows is dangerous because it defeats informed consent and is a strong trust violation, especially in an installer that already requests persistence and network access.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
wallet = open(wallet_file).read().strip() if os.path.exists(wallet_file) else ""
    log(f"Starting miner in foreground (Ctrl+C to stop)...")
    log(f"Tip: Use 'clawrtc start --service' for background auto-restart")
    os.execvp(python_bin, [python_bin, miner_py] + (["--wallet", wallet] if wallet else []))


def cmd_mine(args):
Confidence
85% confidence
Finding
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
if system == "Linux":
        sf = os.path.expanduser("~/.config/systemd/user/clawrtc-miner.service")
        if os.path.exists(sf):
            os.execlp("journalctl", "journalctl", "--user", "-u", "clawrtc-miner", "-f", "--no-pager", "-n", "50")
        else:
            log_file = os.path.join(INSTALL_DIR, "miner.log")
            if os.path.exists(log_file):
Confidence
85% confidence
Finding
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
else:
            log_file = os.path.join(INSTALL_DIR, "miner.log")
            if os.path.exists(log_file):
                os.execlp("tail", "tail", "-f", log_file)
            else:
                warn("No logs found. Start the miner first: clawrtc start")
    elif system == "Darwin":
Confidence
85% confidence
Finding
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
else:
            log_file = os.path.join(INSTALL_DIR, "miner.log")
            if os.path.exists(log_file):
                os.execlp("tail", "tail", "-f", log_file)
            else:
                warn("No logs found. Start the miner first: clawrtc start")
    elif system == "Darwin":
Confidence
85% confidence
Finding
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The CLI's stated purpose is mining/attestation, yet it also includes a BCOS repo scanner, certificate generation, admin-key handling, and network upload workflow. This scope expansion increases attack surface, introduces credential-handling paths unrelated to the advertised function, and makes the package more dangerous in agent contexts where users may not expect these capabilities.

Missing User Warnings

High
Confidence
97% confidence
Finding
BCOS certification reads an admin key from an environment variable or local file and transmits it in an HTTP header without clear user-facing warning. In a skill/agent context, silent credential use is risky because operators may not realize a local secret will be sent over the network, and elsewhere this flow is further weakened by disabled TLS checks.

Memory Manipulation

High
Category
Memory Poisoning
Content
def coinbase_swap_info(args):
    """Show USDC→wRTC swap instructions and Aerodrome pool info."""
    print(f"""
  {GREEN}{BOLD}USDC → wRTC Swap Guide{NC}
Confidence
85% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

External Script Fetching

High
Category
Supply Chain
Content
5. Bridge wRTC to native RTC at https://bottube.ai/bridge

  {DIM}Or use the RustChain API:{NC}
    curl -s https://bulbous-bouffant.metalseed.net/wallet/swap-info
""")
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Content
- VMware, VirtualBox, KVM, QEMU, Xen, Hyper-V, Parallels
    - AWS EC2 (Nitro/Xen), GCP, Azure, DigitalOcean
    - Linode, Vultr, Hetzner, Oracle Cloud, OVH
    - Cloud metadata endpoints (169.254.169.254)

    Updated 2026-02-21: Added cloud provider detection after
    discovering AWS t3.medium instances attempting to mine.
Confidence
90% confidence
Finding
This finding points to documentation/comments describing intentional access to the cloud metadata endpoint, which reinforces that the later network behavior is deliberate rather than incidental. While the comment itself is not executable, in context it signals a design that treats privileged instance-local metadata probing as acceptable, increasing the severity of the implemented requests.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The anti-emulation routine actively probes the cloud metadata service at `169.254.169.254`, which goes beyond passive hardware fingerprinting and introduces network-discovery behavior. In cloud environments this can contact sensitive instance-local services and may retrieve provider-identifying data or tokens, creating SSRF-like access to privileged metadata endpoints without user consent.

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Content
pass

    # --- Cloud metadata endpoint check ---
    # AWS, GCP, Azure, DigitalOcean all use 169.254.169.254
    try:
        import urllib.request
        req = urllib.request.Request(
Confidence
98% confidence
Finding
The code constructs an HTTP request to `http://169.254.169.254/`, a well-known cloud metadata address reachable only from the local host environment. Contacting this special endpoint is SSRF-like behavior against a privileged local service and can leak provider or instance metadata that should not be queried by an unrelated fingerprint routine.

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Content
try:
        import urllib.request
        req = urllib.request.Request(
            "http://169.254.169.254/",
            headers={"Metadata": "true"}
        )
        resp = urllib.request.urlopen(req, timeout=1)
Confidence
99% confidence
Finding
This literal metadata URL is used in a live request, making it a concrete privileged local-service access path. In cloud environments, metadata endpoints can expose sensitive information about the instance and role configuration, so probing them from application code materially increases risk.

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Content
try:
        import urllib.request
        token_req = urllib.request.Request(
            "http://169.254.169.254/latest/api/token",
            headers={"X-aws-ec2-metadata-token-ttl-seconds": "5"},
            method="PUT"
        )
Confidence
99% confidence
Finding
The IMDSv2 token request targets AWS's protected metadata token endpoint, which is especially sensitive because successful token acquisition can be a precursor to broader metadata access. Even though this code only checks for status 200, it still performs an unauthorized probe against a privileged cloud control surface unrelated to local hardware validation.

YARA rule 'crypto_miner_software': References to known cryptocurrency mining software [cryptominers]

High
Category
YARA Match
Content
#!/usr/bin/env python3
"""
RustChain Windows Wallet Miner
Full-featured wallet and miner for Windows

Includes Zephyr (RandomX) dual-mining integration.
See: https://github.com/Scottcjn/rustchain-bounties/issues/461
"""

import os
import sys
import time
import json
import hashlib
import platform
import threading
import statistics
import uuid
import subprocess
import re
try:
    import tkinter as tk
    from tkinter import ttk, messagebox, scrolledtext
    TK_AVAILABLE = True
    _TK_IMPORT_ERROR = ""
except Exception as e:
    TK_AVAILABLE = False
    _TK_IMPORT_ERROR = str(e)
    tk = None
    ttk = None
    messagebox = None
    scrolledtext = None
import requests
from datetime import datetime
from pathlib i
Confidence
99% confidence
Finding
The file is explicitly a cryptocurrency miner with dual-mining support and detection of `xmrig`/`zephyrd`, not merely an incidental reference. In an agent-skill ecosystem, embedded cryptomining logic is highly dangerous because it can abuse host CPU resources, generate unauthorized network traffic, and pair naturally with the undisclosed telemetry and insecure remote communications present elsewhere in the file.

Missing User Warnings

High
Confidence
98% confidence
Finding
The miner automatically sends attestation and enrollment-related data to remote endpoints with no meaningful user-facing disclosure or informed consent. This is particularly dangerous here because the file is not a generic admin tool but a crypto-mining client that starts repeated background network communication to a hard-coded node, making covert telemetry and wallet-associated tracking plausible.

Missing User Warnings

High
Confidence
99% confidence
Finding
The attestation payload includes sensitive hardware identifiers such as MAC addresses, hostname, CPU details, architecture, and device model, which can be used to fingerprint a user across installs and networks. In this skill's context—a cryptocurrency miner that silently phones home to a hard-coded external node over HTTP—this collection is especially dangerous because it enables persistent device tracking and deanonymization without meaningful user awareness or consent.

Static analysis

Detected: malicious.crypto_mining, suspicious.dynamic_code_execution, suspicious.exposed_secret_literal (+1 more)

Possible crypto mining behavior detected.

Critical
Code
malicious.crypto_mining
Location
clawrtc/data/miner.py:86

Possible crypto mining behavior detected.

Critical
Code
malicious.crypto_mining
Location
clawrtc/data/pow_miners.py:24

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
clawrtc/cli.py:815

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
clawrtc/cli.py:649

HTTPS certificate verification is disabled.

Warn
Code
suspicious.insecure_tls_verification
Location
clawrtc/cli.py:502