Back to skill

Security audit

Crypto Whale Monitor

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says: it checks listed Ethereum wallet balances through a public RPC endpoint and prints alerts, with no hidden install hooks or destructive behavior found.

Install only if you are comfortable sending the wallet addresses you monitor to the default or configured Ethereum RPC provider. If you schedule it with cron, review the frequency and endpoint yourself, since that will create recurring network requests.

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

Note
Location
scripts/monitor.js:82
Finding

Unvalidated RPC Balance Response Can Terminate the Monitor

Content
View full analysis

Vulnerability Details

File Location: scripts/monitor.js:82-100
Vulnerability Type: Insufficient validation of untrusted RPC response data
Risk Level: Low

Vulnerable Code:

js
        const data = await response.json();
        if (data.error) {
            throw new Error(`RPC Error: ${data.error.message}`);
        }

        return data.result; // Hex string
    } catch (error) {
        console.error(`[!] Failed to check ${address}: ${error.message}`);
        return null;
    }
}

// ...

    for (const address of wallets) {
        const hexBalance = await getBalance(address);
        
        if (hexBalance) {
            const balanceWei = BigInt(hexBalance);

Technical Analysis

The RPC endpoint is an external trust boundary, but the monitor does not validate that data.result is a valid Ethereum hexadecimal quantity before returning it. The value is subsequently supplied to BigInt() outside the getBalance() exception handler.

If the configured, compromised, or malfunctioning RPC endpoint returns a successful JSON response containing a malformed, nonempty result, such as "invalid", BigInt(hexBalance) throws a SyntaxError. This rejects main() and reaches the top-level fatal-error handler, terminating the process rather than isolating the failure to the affected wallet.

Attack Path

  1. The operator configures an attacker-controlled endpoint through RPC_URL, or the selected RPC endpoint becomes compromised or malfunctioning.

  2. The monitor submits an eth_getBalance request.

  3. The endpoint returns an HTTP-successful JSON response such as:

    json
    {
      "jsonrpc": "2.0",
      "id": 1,
      "result": "invalid"
    }
    
  4. getBalance() returns the malformed, nonempty result.

  5. BigInt("invalid") throws outside the per-request try...catch.

  6. The top-level rejection handler exits the process, preventing the ...[truncated 477 chars]

Remediation
View remediation

Remediation Suggestions

Validate the RPC response structure and quantity format before conversion. Ethereum JSON-RPC quantities should be hexadecimal strings with a 0x prefix and canonical numeric content. For example:

js
function isValidRpcQuantity(value) {
    return typeof value === 'string'
        && /^0x(?:0|[1-9a-fA-F][0-9a-fA-F]*)$/.test(value);
}

Reject responses that lack a valid result, and move the BigInt() conversion into a per-wallet try...catch so one malformed response cannot terminate the complete scan:

js
if (!isValidRpcQuantity(data.result)) {
    throw new Error('RPC returned an invalid balance quantity');
}

return BigInt(data.result);

The caller should consume the validated BigInt directly and continue processing other wallets after any individual failure. Additionally, use an AbortController timeout and an appropriate response-size limit to reduce exposure to stalled or excessively large RPC responses.

Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill describes executing JavaScript that performs network access to public Web3 RPC endpoints and may read environment variables, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization gap where consumers cannot clearly constrain or review the skill's runtime capabilities, increasing the chance of unintended network access, secret exposure, or broader-than-expected execution behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code hard-codes toLocaleString('en-US', ...), which imposes a specific language/locale format on all users. The policy for this category says locale-specific behavior should not be forced unless the user can opt in or the constraint is clearly justified.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/monitor.js:19