Back to skill

Security audit

agenta-monero

Security checks across malware telemetry and agentic risk

Overview

This skill is openly for Monero payments, but it can broadcast irreversible sends or sweep a wallet without an enforced confirmation step.

Install only if you are comfortable giving an agent access to a real Monero wallet. Use stagenet first, keep only small amounts in the wallet, run on a single-user machine or isolated container, protect .env from backups/logs/version control, and require your own explicit human approval before any send_xmr.sh or sweep_all.sh call without --dry-run.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (20)

Vague Triggers

Medium
Confidence
88% confidence
Finding
The setup instruction is intentionally broad natural language ('Set up the Agenta-Monero skill.') and encourages agent-driven configuration for a wallet-handling skill that can later send or sweep funds. In an autonomous agent context, ambiguous activation language increases the chance of unintended installation or configuration of a high-risk financial capability, especially if user intent is inferred loosely or prompt-injection influences the agent.

Missing User Warnings

High
Confidence
97% confidence
Finding
The script invokes the Monero wallet RPC `transfer` method directly, which can broadcast an irreversible cryptocurrency payment, but the file contains no user-facing confirmation, explicit consent checkpoint, destination recap, or protective interlock before doing so. In a wallet/payment skill, this is especially dangerous because any upstream prompt injection, parameter mix-up, or agent mistake can immediately turn into loss of funds, and Monero transactions are privacy-preserving and practically irreversible once relayed.

Missing User Warnings

High
Confidence
94% confidence
Finding
This script invokes the Monero wallet RPC `sweep_all` operation directly and will relay the transaction by default unless `--dry-run` is explicitly provided. Because sweeping moves essentially all available funds and Monero transactions are irreversible, the lack of any confirmation gate, explicit safety interlock, or default non-broadcast mode creates a real risk of accidental total-fund transfer if the script is called with a wrong address or by a higher-level agent without strong user confirmation.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
This test intentionally writes a wallet password to stdout via `echo "wp=${MONERO_WALLET_PASSWORD}"`, which exposes a secret in user-visible output and potentially in CI logs, test artifacts, and terminal history. Even though the value is a test secret, this pattern normalizes unsafe handling of wallet credentials and could leak real secrets if reused or if test environments are misconfigured.

External Transmission

Medium
Category
Data Exfiltration
Content
[[ -n "${MONERO_RPC_SSL_CACERT:-}" ]] && args+=(--cacert "$MONERO_RPC_SSL_CACERT")
    [[ -n "${MONERO_RPC_SSL_CAPATH:-}" ]] && args+=(--capath "$MONERO_RPC_SSL_CAPATH")
  }
  curl "${args[@]}" -d "$body"
}

rpc_call() {
Confidence
93% confidence
Finding
curl "${args[@]}" -d

Credential Access

High
Category
Privilege Escalation
Content
shell_execution: true
    file_writes:
      - ".env (chmod 600) — RPC credentials + wallet password"
      - "$MONERO_LOCK_DIR/.netrc (chmod 600) — ephemeral RPC auth"
      - "$MONERO_LOCK_DIR/wallet-rpc.pid — process tracking"
      - "$MONERO_LOCK_DIR/wallet-rpc.port — port tracking"
      - "$MONERO_LOCK_DIR/.last_refresh — refresh timestamp"
Confidence
88% confidence
Finding
/.netrc

Credential Access

High
Category
Privilege Escalation
Content
- "$MONERO_LOCK_DIR/.last_refresh — refresh timestamp"
    process_management: "starts/stops monero-wallet-rpc as a background process"
    network_access: "HTTP POST to $MONERO_RPC_URL/json_rpc (localhost by default)"
    credential_access: "reads .env for RPC + wallet credentials; writes .netrc for curl auth"
---

# Agenta-Monero
Confidence
93% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
| Capability | Details |
|------------|---------|
| **Shell execution** | Runs `curl`, `jq`, `flock`, `monero-wallet-rpc`, and standard shell utilities |
| **File writes** | `.env` (chmod 600), `.netrc` (chmod 600, ephemeral), PID/port files, lock files, refresh timestamp |
| **Process management** | Starts and stops `monero-wallet-rpc` as a background daemon (PID tracked in `$MONERO_LOCK_DIR`) |
| **Network access** | HTTP POST to `$MONERO_RPC_URL/json_rpc` (localhost by default; can be configured for remote) |
| **Credential access** | Reads `.env` for RPC user/password and wallet password; writes `.netrc` for curl auth; never emits credentials in stdout |
Confidence
90% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
| **File writes** | `.env` (chmod 600), `.netrc` (chmod 600, ephemeral), PID/port files, lock files, refresh timestamp |
| **Process management** | Starts and stops `monero-wallet-rpc` as a background daemon (PID tracked in `$MONERO_LOCK_DIR`) |
| **Network access** | HTTP POST to `$MONERO_RPC_URL/json_rpc` (localhost by default; can be configured for remote) |
| **Credential access** | Reads `.env` for RPC user/password and wallet password; writes `.netrc` for curl auth; never emits credentials in stdout |

All credential files are created with restrictive permissions (`0600` for files, `0700` for the lock directory). The `.env` file is parsed safely (never sourced) and shell metacharacters are rejected.
Confidence
87% confidence
Finding
.netrc

Credential Access

High
Category
Privilege Escalation
Content
- **`validate_address` uses real RPC fields.** The RPC is called with `any_net_type:true` so the real `nettype` is returned; `network_match` is derived client-side by comparing `nettype` to `MONERO_NETWORK`. There is **no `checksum_valid` field** (the checksum is part of `valid`). This keeps `INVALID_ADDRESS` (bad format/checksum) distinct from `NETWORK_MISMATCH` (valid but wrong network).
- **Money is integer piconeros (1 XMR = 10^12).** Never use floating-point for amounts. All arithmetic is integer piconero; the XMR decimal strings in output come from the scripts' string-based conversion. Amounts must be positive and have <=12 decimals.
- **Sends and sweeps are not idempotent and are NOT auto-retried.** On timeout/uncertain result, check `get_transfer.sh --tx-hash` **before** retrying (see retry-safety workflow). Use `--dry-run` / `estimate_fee` to preview.
- **Credentials use netrc (never `curl -u`); `.env` is parsed, never sourced.** The netrc lives at `$MONERO_LOCK_DIR/.netrc` (mode `0600`). All user values are passed to the RPC via `jq --arg`/`--argjson` — never by string interpolation.

## Workflows
Confidence
86% confidence
Finding
/.netrc

Credential Access

High
Category
Privilege Escalation
Content
permissions:
    shell_execution: true
    file_writes:
      - ".env (chmod 600) — RPC credentials + wallet password"
      - "$MONERO_LOCK_DIR/.netrc (chmod 600) — ephemeral RPC auth"
      - "$MONERO_LOCK_DIR/wallet-rpc.pid — process tracking"
      - "$MONERO_LOCK_DIR/wallet-rpc.port — port tracking"
Confidence
93% confidence
Finding
.env

Credential Access

High
Category
Privilege Escalation
Content
- "$MONERO_LOCK_DIR/.last_refresh — refresh timestamp"
    process_management: "starts/stops monero-wallet-rpc as a background process"
    network_access: "HTTP POST to $MONERO_RPC_URL/json_rpc (localhost by default)"
    credential_access: "reads .env for RPC + wallet credentials; writes .netrc for curl auth"
---

# Agenta-Monero
Confidence
93% confidence
Finding
.env

Credential Access

High
Category
Privilege Escalation
Content
ensure_netrc() {
  local dir="${MONERO_LOCK_DIR:-/tmp/agenta-monero}"
  mkdir -p "$dir"; chmod 700 "$dir" 2>/dev/null || true
  NETRC_FILE="$dir/.netrc"
  local host; host=$(printf '%s' "${MONERO_RPC_URL:-}" | sed -E 's#^[a-z]+://##; s#[:/].*$##')
  : "${host:=127.0.0.1}"
  local user="${MONERO_RPC_USER:-}" pass="${MONERO_RPC_PASSWORD:-}"
Confidence
84% confidence
Finding
/.netrc

Credential Access

High
Category
Privilege Escalation
Content
RPC_USER=$(gen_random 12)
RPC_PASSWORD=$(gen_random 24)

# --- Resolve .env path ---
ENV_FILE="$SCRIPT_DIR/../.env"

if [[ -f "$ENV_FILE" && "$FORCE" != true ]]; then
Confidence
84% confidence
Finding
.env

Credential Access

High
Category
Privilege Escalation
Content
[[ "$answer" =~ ^[yY] ]] || json_error "CONFIG_INVALID" "setup cancelled by user"
fi

# --- Write .env ---
cat > "$ENV_FILE" <<EOF
# === Monero Wallet RPC Connection ===
MONERO_RPC_URL="http://127.0.0.1:$RPC_PORT"
Confidence
95% confidence
Finding
.env

Credential Access

High
Category
Privilege Escalation
Content
[[ "$output" == *"auto=false"* ]]
}

@test "script_init exports MONERO_WALLET_PASSWORD from .env" {
  d="$(mktemp -d)"; printf 'MONERO_NETWORK="mainnet"\nMONERO_RPC_URL="http://127.0.0.1:18099"\nMONERO_LOCK_DIR="%s"\nMONERO_WALLET_PASSWORD="secret123"\n' "$(mktemp -d)" > "$d/.env"
  mkdir -p "$d/lib" "$d/scripts"
  cp "$LIB"/*.sh "$d/lib/"
Confidence
90% confidence
Finding
.env"

Credential Access

High
Category
Privilege Escalation
Content
}

@test "script_init exports MONERO_WALLET_PASSWORD from .env" {
  d="$(mktemp -d)"; printf 'MONERO_NETWORK="mainnet"\nMONERO_RPC_URL="http://127.0.0.1:18099"\nMONERO_LOCK_DIR="%s"\nMONERO_WALLET_PASSWORD="secret123"\n' "$(mktemp -d)" > "$d/.env"
  mkdir -p "$d/lib" "$d/scripts"
  cp "$LIB"/*.sh "$d/lib/"
  cat > "$d/scripts/x.sh" <<'SH'
Confidence
90% confidence
Finding
.env"

Credential Access

High
Category
Privilege Escalation
Content
# Verify .env was written
  [[ -f "$skill_copy/.env" ]]
  local env_contents
  env_contents=$(cat "$skill_copy/.env")
  [[ "$env_contents" == *"MONERO_NETWORK=\"stagenet\""* ]]
  [[ "$env_contents" == *"MONERO_WALLET_PASSWORD=\"walletpass\""* ]]
  [[ "$env_contents" == *"MONERO_WALLET_NAME=\"$wallet_dir/test_wallet\""* ]]
Confidence
91% confidence
Finding
.env"

Unsafe Defaults

Medium
Category
Tool Misuse
Content
**Both paths:**
- Generate random RPC credentials (12-char user, 24-char password).
- Write `.env` (chmod 600) with all values including `MONERO_WALLET_PASSWORD`.
  - **Caution:** `.env` persists on disk and contains the wallet password. On multi-user systems or CI, ensure the file is not world-readable, not committed to version control, and not included in backups or log captures.
- Start `monero-wallet-rpc` as a background process (PID stored in `$MONERO_LOCK_DIR/wallet-rpc.pid`).
- Run `./setup.sh` and report readiness.
- **Credentials are not emitted in stdout JSON.** They exist only in `.env` (chmod 600). If the user needs to see them, read from `.env` directly.
Confidence
84% confidence
Finding
world-readable

Tool Parameter Abuse

High
Category
Tool Misuse
Content
kill -0 "$pid" 2>/dev/null || stopped=true
    fi
  fi
  rm -f "$PID_FILE" "$PORT_FILE" 2>/dev/null || true
fi

jq -nc --argjson stopped "$stopped" --argjson pid "${pid:-null}" \
Confidence
86% confidence
Finding
rm -f "$PID_FILE" "$PORT_FILE" 2>/dev/

VirusTotal

63/63 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.