Back to skill

Security audit

Ripley Pocket For Monero

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed crypto payment API guide, but it includes broad activation language and an automatic payment helper that could spend funds without clear user approval or limits.

Install only if you intentionally want an agent to use a Ripley Pocket API key for crypto payments. Keep the API key scoped and protected, require manual approval before every payment, withdrawal, swap, or XMR402 payment, set strict spend limits and trusted-domain allowlists outside the skill, and be aware that crypto transactions may be irreversible.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:429
Finding

Unbounded Automatic Cryptocurrency Payment from Untrusted XMR402 Challenges

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 429–447
Vulnerability Type: Automatic payment authorization using attacker-controlled challenge fields
Risk Level: High

Vulnerable Code

python
def call_with_xmr402(url: str, method: str = "GET", headers: dict = {}, **kwargs) -> httpx.Response:
    """Hit a URL; if it returns 402 with XMR402 challenge, pay via Ripley Pocket and retry."""
    resp = httpx.request(method, url, headers=headers, **kwargs)

    if resp.status_code != 402:
        return resp

    www_auth = resp.headers.get("WWW-Authenticate", "")
    if not www_auth.startswith("XMR402"):
        return resp  # Not an XMR402 challenge

    # Parse the challenge
    challenge = parse_xmr402_challenge(www_auth)
    address = challenge["address"]
    amount = int(challenge["amount"]) / 1e12  # piconeros → XMR
    message = challenge["message"]

    # Pay via Ripley Pocket (synchronous — returns txid + proof)
    pay_resp = httpx.post(f"{RIPLEY_URL}/xmr402/pay", headers=PAY_HEADERS, json={
        "address": address,
        "amount": amount,
        "message": message,
    }).json()

Technical Analysis

The helper treats the address, amount, and message values in an HTTP WWW-Authenticate response as authorization to initiate an irreversible cryptocurrency payment. These fields are controlled by the remote endpoint that returns the response.

After checking only that the header begins with XMR402, the function submits the supplied destination and amount to the authenticated /xmr402/pay endpoint. It does not require user confirmation or enforce a maximum payment amount, cumulative spending budget, trusted-origin policy, destination allowlist, or balance-based safety threshold. It also does not validate the challenge timestamp or expiration.

Consequently, any malicious or compromised endpoint contacted through this helper can request a payment to an attacker-selected Monero address. Redirects may create an ...[truncated 1703 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require explicit user approval before submitting every payment. Present the normalized destination address, XMR amount, network fee, merchant origin, and total debit.
  2. Enforce a strict configurable maximum amount per transaction and cumulative spending limits per session, merchant, and time period.
  3. Permit automatic payment only for explicitly allowlisted HTTPS origins and expected destination addresses. Revalidate the final origin after every redirect or disable redirects for payment-triggering requests.
  4. Validate every challenge field before payment:
    • Require all mandatory fields.
    • Reject non-numeric, negative, zero, non-finite, or excessive amounts.
    • Validate the complete Monero address format.
    • Check timestamp freshness and expiration.
    • Reject duplicate or replayed messages.
  5. Check the account balance and calculated fee before requesting payment. Refuse transactions that would exceed a configured reserve threshold.
  6. Bind approval to the exact request method, URL, body digest, merchant origin, amount, address, and nonce so that approval cannot be reused for a different request.
  7. Record an auditable authorization decision for each payment and provide a mechanism to disable automatic XMR402 handling.
  8. Replace the mutable default argument with a safe default:
python
def call_with_xmr402(
    url: str,
    method: str = "GET",
    headers: dict | None = None,
    **kwargs,
) -> httpx.Response:
    headers = {} if headers is None else dict(headers)
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

YARA rule 'ransomware_behavior': Ransomware-like patterns (mass encryption, ransom notes) [malware]

Critical
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · SKILL.md (reported line 3)May include surrounding context.

md
---
name: ripley-pocket
description: "API client skill for Ripley Pocket — the M2M micro-payment gateway for AI agents. Use this skill whenever you need to: send or receive payments between AI agents, check an agent's XMR balance, withdraw Monero to an external address, swap XMR cross-chain to BTC/ETH/USDT/LTC, deposit BTC/ETH/USDT/LTC and auto-convert to XMR balance, register a new agent account, or view transaction history. Triggers on any mention of Ripley Pocket, agent payments, XMR/Monero payments, micro-payments between agents, POST /pay, X-API-KEY, deposit swap, fund account with BTC/ETH, or the XMR402 payment protocol. Also use when the user wants to integrate an AI agent with a payment system, fund an agent wallet with non-XMR crypto, or

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation provides direct instructions for irreversible payment, withdrawal, and swap operations without requiring an explicit confirmation step or warning about finality, fees, destination verification, and inability to recover funds. In a custodial crypto payment context, this omission is dangerous because a user or downstream agent could follow the examples and send funds to the wrong recipient or chain with no practical recourse.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill advertises extremely broad activation triggers such as generic payment, crypto, and API-key related requests, which can cause the agent to invoke this high-risk payment skill outside clearly intended Ripley Pocket scenarios. In a financial skill that can transfer funds, withdraw crypto, and initiate swaps, over-triggering materially increases the chance of unintended or user-unauthorized actions.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 45)May include surrounding context.

No authentication required. Returns an API key and deposit address. The account is inactive until a minimum deposit of 0.01 XMR arrives.

bash
curl -X POST $RIPLEY_URL/register \
  -H "Content-Type: application/json" \
  -d '{"name": "My Agent"}'

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

The tracking URL reveals dependence on an additional third-party swap provider domain, which expands the data-sharing and trust boundary beyond the primary Ripley Pocket service. Users or agents may unknowingly disclose transaction metadata to that third party, and the skill does not clearly warn about this external dependency or its privacy and integrity implications.

Content

Scanner excerpt · SKILL.md (reported line 161)May include surrounding context.

"trade_id": "abc123", "xmr_deducted": 0.158432, "eta_minutes": 10, "tracking_url": "https://api.kyc.rip/v2/exchange/status/abc123" }

text

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

Like the outbound swap tracking URL, this deposit-swap tracking URL introduces a third-party service into the workflow and may expose deposit and trade metadata to that service. In a cryptocurrency funding flow, undisclosed third-party dependencies increase privacy, compliance, and tampering concerns for operators using the skill.

Content

Scanner excerpt · SKILL.md (reported line 195)May include surrounding context.

"send_currency": "BTC", "xmr_expected": 0.1567, "eta_minutes": 15, "tracking_url": "https://api.kyc.rip/v2/exchange/status/xyz789" }

text

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This endpoint example transmits a request that directly causes an on-chain payment and proof generation, making it more than a generic external call. Because it can spend funds synchronously based on challenge data from another service, inadequate user consent, origin validation, or amount limits could let an agent auto-pay untrusted endpoints or attacker-supplied challenges.

Content

Scanner excerpt · SKILL.md (reported line 301)May include surrounding context.

Synchronous endpoint — broadcasts the XMR transfer and returns the TX proof in one shot (~1-2 seconds).

bash
curl -X POST $RIPLEY_URL/xmr402/pay \
  -H "X-API-KEY: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{

Static analysis

No suspicious patterns detected.