other
- Location
clawrtc/data/miner.py:156- Finding
<![CDATA[Undisclosed Transmission of Hostname and MAC Addresses]]>
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
ClawRTC is mostly coherent as a crypto-mining and hardware-attestation tool, but it under-discloses telemetry and device identifiers and has unsafe wallet/service handling that users should review before installing.
Review this carefully before installing. It is a token miner that can run continuously, use CPU, create wallet files, contact external services, and optionally install a user-level background service. The main risks are privacy from hostname/MAC transmission and silent install telemetry, plus local wallet/service hardening issues; avoid `--service` and private-key export unless you understand those tradeoffs.
clawrtc/data/miner.py:156<![CDATA[Undisclosed Transmission of Hostname and MAC Addresses]]>
clawrtc/cli.py:319<![CDATA[Undisclosed Installation Telemetry Sent to a Third Party]]>
clawrtc/cli.py:735<![CDATA[Private Wallet Exports Are Created Without Restrictive Permissions]]>
clawrtc/data/miner.py:329<![CDATA[Predictable Shared Temporary File Permits Symlink-Based File Clobbering]]>
clawrtc/cli.py:377<![CDATA[Wallet Input Can Inject Persistent Service Configuration]]>
clawrtc/cli.py:271<![CDATA[Runtime Installation Uses Mutable Unpinned Dependencies]]>
Using shell=True in a generic command wrapper significantly increases the attack surface because any interpolated parameter can become shell syntax. In this file, that wrapper is used for service-management and environment-setup commands, and some inputs such as wallet values are user-controlled, making command injection plausible in an agent or automated installation context.
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
)
The consent disclosure states that no data is sent to any third party, but the code later posts telemetry to bottube.ai. Misrepresenting data flows is dangerous because it defeats user consent and can hide privacy-impacting behavior behind reassuring text.
File contents flow to a network sink. This may indicate data exfiltration of sensitive files.
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:
File contents flow to a network sink. This may indicate data exfiltration of sensitive files.
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:
File contents flow to a network sink. This may indicate data exfiltration of sensitive files.
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:
The installer silently sends install telemetry to a third-party domain in a background thread without opt-in, while the disclosure text claims no data is sent to any third party. Even if the payload omits obvious PII, it still leaks installation metadata externally and undermines informed consent.
data=payload,
headers={"Content-Type": "application/json"}
)
urllib.request.urlopen(req, timeout=5)
except Exception:
pass
threading.Thread(target=_ping, daemon=True).start()
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
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_stop(args):
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
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):
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
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":
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
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":
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.
def coinbase_swap_info(args):
"""Show USDC→wRTC swap instructions and Aerodrome pool info."""
print(f"""
{GREEN}{BOLD}USDC → wRTC Swap Guide{NC}
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
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
""")
Using subprocess.run with shell=True is a classic unsafe execution pattern because the shell interprets metacharacters, expansions, and pipelines. In an agent skill, this is especially risky since future parameter reuse, refactoring, or indirect control paths can turn seemingly harmless hardware queries into arbitrary command execution.
def _run_cmd(self, cmd):
try:
return subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
text=True, timeout=10, shell=True).stdout.strip()
except:
return ""
The attestation payload sends hardware characteristics, hostname, MAC addresses, entropy-derived fingerprints, and optional fingerprint-check results to a remote third-party node. This creates device tracking and privacy risk, and in an agent setting is more dangerous because users may invoke the skill expecting local analysis rather than exfiltration of stable identifiers.
The README explicitly states that the agent performs hardware fingerprinting and automatic recurring attestation to a network, but it does not clearly disclose what device characteristics are collected, what is transmitted, how often it is sent, how long it is retained, or who can access it. In an agent-installation context, this is dangerous because users may authorize persistent background telemetry and uniquely identifying device data without informed consent, enabling privacy loss, tracking, and unexpected outbound communication.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Usage:
pip install clawrtc
clawrtc wallet create Generate your RTC address
clawrtc install --wallet RTC...
clawrtc start
The helper uses subprocess.run with shell=True on dynamically constructed command strings throughout the CLI. Several call sites interpolate values derived from user input or files, such as wallet names and plist paths, which creates command injection risk if those values contain shell metacharacters.
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
)
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
elif system == "Darwin":
try:
out = subprocess.run(
["sysctl", "-n", "machdep.cpu.features"],
capture_output=True, text=True
).stdout.lower()
The disclosure says 'No external downloads — all code ships with the package,' yet installation performs pip upgrades and installs requests from external package sources. This is misleading and materially affects the trust and supply-chain risk profile presented to users.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
wallet = f"claw-{hostname}-{int(time.time()) % 100000}"
warn(f"No wallet name provided. Auto-generated: {wallet}")
# Create install dir
log(f"Installing to {INSTALL_DIR}")
os.makedirs(INSTALL_DIR, exist_ok=True)
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
try:
run_cmd("systemctl --user daemon-reload")
run_cmd("systemctl --user enable clawrtc-miner")
run_cmd("systemctl --user start clawrtc-miner")
success("Service installed and started (auto-restarts on reboot)")
except Exception:
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
def _setup_launchd(wallet):
"""Set up launchd agent on macOS."""
plist_dir = os.path.expanduser("~/Library/LaunchAgents")
os.makedirs(plist_dir, exist_ok=True)
plist_file = os.path.join(plist_dir, "com.clawrtc.miner.plist")
python_bin = os.path.join(VENV_DIR, "bin", "python")
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
def _setup_launchd(wallet):
"""Set up launchd agent on macOS."""
plist_dir = os.path.expanduser("~/Library/LaunchAgents")
os.makedirs(plist_dir, exist_ok=True)
plist_file = os.path.join(plist_dir, "com.clawrtc.miner.plist")
python_bin = os.path.join(VENV_DIR, "bin", "python")
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
def _setup_launchd(wallet):
"""Set up launchd agent on macOS."""
plist_dir = os.path.expanduser("~/Library/LaunchAgents")
os.makedirs(plist_dir, exist_ok=True)
plist_file = os.path.join(plist_dir, "com.clawrtc.miner.plist")
python_bin = os.path.join(VENV_DIR, "bin", "python")
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
def _setup_launchd(wallet):
"""Set up launchd agent on macOS."""
plist_dir = os.path.expanduser("~/Library/LaunchAgents")
os.makedirs(plist_dir, exist_ok=True)
plist_file = os.path.join(plist_dir, "com.clawrtc.miner.plist")
python_bin = os.path.join(VENV_DIR, "bin", "python")
No suspicious patterns detected.