Back to skill

Security audit

Bitcoin Wallet for Agents using Arkade

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real cryptocurrency wallet skill, but it needs review because some docs can expose wallet keys and the install examples execute mutable packages.

Review carefully before installing. Do not pass any private key or seed phrase to the CLI, pin and verify package versions instead of using unpinned npx/dlx commands, keep only small/test funds unless you trust the package and host, and require explicit confirmation for every send, offboard, Lightning payment, swap, claim, or refund.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
README.md:49
Finding

Private Key Exposure Through Incorrect Command-Line Documentation

Content
View full analysis
``` ``` The command table repeats the unsafe interface: ```markdown | `init [url]` | Initialize wallet | ``` The actual implementation interprets the first argument as a server URL rather than a private key: ```javascript async function cmdInit(serverUrl) { const existing = loadConfig(); if (existing) { const { sdk } = await getSDK(); const { Wallet, SingleKey } = sdk; const wallet = await Wallet.create({ identity: SingleKey.fromHex(existing.privateKey), arkServerUrl: existing.serverUrl || DEFAULT_SERVER, }); const address = await wallet.getAddress(); console.log("Wallet already initialized."); console.log(`Server: ${existing.serverUrl || DEFAULT_SERVER}`); console.log(`Address: ${address}`); return; } try { const config = await autoInit(serverUrl); ``` ### Technical Analysis The README explicitly directs users to place a Bitcoin private key in a command-line argument. Command-line secrets can be exposed through: - Shell history files - Process listings and process-monitoring utilities - Terminal session recording - CI/CD logs - Agent transcripts and tool-call logs - Audit and telemetry systems The implementation makes the issue more dangerous because `cmdInit` does not import the supplied private key. It treats the argument as `serverUrl` and independently generates a new wallet through `autoInit`. A user may consequently disclose an existing wallet key while unknowingly initializing a different wallet. This violates secure secret-entry principles: cryptographic credentials must not be accepted or requested through process arguments. ### Attack Path 1. A user follows the README ...[truncated 1210 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
cli/arkade.mjs:54
Finding

Non-Atomic Creation of Wallet Credential File

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:48
Finding

Unpinned Remote Package Execution in Installation Instructions

Content
View full analysis
Remediation
View remediation
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (41)

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 · README.md (reported line 115)May include surrounding context.

md
ds

| Command | Description |
|---------|-------------|
| `init <key> [url]` | Initialize wallet |
| `address` | Show Ark address |
| `boarding-address` | Show boarding address |
| `balance` | Show balance breakdown |
| `send <addr> <amt>` | Send sats |
| `history` | Transaction history |
| `onboard` | Get paid onchain: convert received onchain BTC to offchain |
| `offboard <addr>` | Pay onchain: send offchain BTC to an onchain address |
| `ln-invoice <amt>` | Create Lightning invoice |
| `ln-pay <bolt11>` | Pay Lightning invoice |
| `ln-fees` | Show swap fees |
| `ln-limits` | Show swap limits |
| `swap-quote <amt> <from> <to>` | Get stablecoin quote |
| `swap-to-stable <amt> <token> <chain> <addr>` | Swap BTC to stablecoin |
| `swap-to-btc <amt> <token> <chain> <addr>` | Swap stablecoin to BTC |
| `swap-status <id>` | Check swap status |
| `swap-pending` | Show pending swaps |
| `swap-pairs` | Show trading pairs |

## Configuration

- **Data:** `~/.arkade-wallet/config.json`

## Docu

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 125)May include surrounding context.

bash
# Send sats to an Ark address
arkade send <ark-address> <amount-sats>

# Example: Send 50,000 sats
arkade send ark1qxyz... 50000

# View transaction history
arkade history

Onchain Payments (Onboard/Offboard)

bash
# Get paid onchain: Receive BTC to your boarding address, then onboard to Arkade
# Step 1: Get your boarding address
arkade boarding-address

# Step 2: Have someone send BTC to your boarding address

# Step 3: Onboard the received BTC to make it available offchain
arkade onboard

# Pay onchain: Send offchain BTC to any onchain Bitcoin address
arkade offboard <btc-address>

# Example: Pay someone at bc1 address
arkade offboard bc1qxyz...

Lightning Network

bash
# Create a Lightning invoice to receive payment
arkade ln-invoice <amount-sats> [description]

# Example: Create invoice for 25,000 sats
arkade ln-invoice 25000 "Coffee payment"

# Pay a Lightning invoice
arkade ln-pay <bolt11-invoice>

# Show swap fees
arkade ln-fees

# Show swap limits

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 · cli/arkade.mjs (reported line 373)May include surrounding context.

js
{ ArkadeBitcoinSkill } = skill;

  const config = loadConfig();
  const arkProvider = new RestArkProvider(config.serverUrl || DEFAULT_SERVER);
  const arkInfo = await arkProvider.getInfo();

  const bitcoin = new ArkadeBitcoinSkill(wallet);
  const balance = await bitcoin.getBalance();

  if (balance.onchain.total === 0) {
    console.log("No boarding UTXOs to onboard.");
    console.log(
      `Send BTC to your boarding address: ${await wallet.getBoardingAddress()}`,
    );
    return;
  }

  console.log(`Onboarding ${formatSats(balance.onchain.total)} sats...`);

  try {
    const result = await bitcoin.onboard({
      feeInfo: arkInfo.feeInfo,
      eventCallback: (event) => {
        console.log(`  Event: ${event.type}`);
      },
    });

    console.log(`Onboarded successfully!`);
    console.log(`Commitment TX: ${result.commitmentTxid}`);
  } catch (e) {
    console.error(`Error: ${e.message}`);
    process.exit(1);
  }
}

/**
 * Offboard command.
 */
async function cmdOffboard

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 · src/skills/arkadeBitcoin.ts (reported line 38)May include surrounding context.

ts
dResult,
  BalanceInfo,
  IncomingFundsEvent,
  OnboardParams,
  OffboardParams,
  RampResult,
} from "./types";

/**
 * ArkadeBitcoinSkill provides a unified interface for sending and receiving
 * Bitcoin over the Arkade protocol.
 *
 * This skill wraps the core wallet functionality and provides:
 * - Offchain Bitcoin transactions via Ark
 * - Get paid onchain via boarding address + onboard
 * - Pay onchain via offboard to any Bitcoin address
 * - Balance management
 * - Transaction history
 *
 * @example
 * ```typescript
 * import { Wallet, SingleKey } from "@arkade-os/sdk";
 * import { ArkadeBitcoinSkill } from "@arkade-os/skill";
 *
 * // Create a wallet
 * const wallet = await Wallet.create({
 *   identity: SingleKey.fromHex(privateKeyHex),
 *   arkServerUrl: "https://arkade.computer",
 * });
 *
 * // Create the skill
 * const bitcoinSkill = new ArkadeBitcoinSkill(wallet);
 *
 * // Get addresses for receiving
 * const addresses = await bitcoinSkill.getReceiveAddresses();
 * consol

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The implemented code aligns well with the Arkade/offchain/onchain Bitcoin portions of the description: it supports Ark receive/send, boarding address retrieval, balance/history, incoming-funds notifications, onboard, and offboard. However, the declared description materially overstates functionality by claiming Lightning send/receive and USDC/USDT swaps, neither of which appears anywhere in the code. There are no unrelated dangerous capabilities beyond the Bitcoin/Arkade wallet operations, but the description does not accurately represent the full implemented scope because two advertised primary capabilities are absent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code chunk is narrowly focused on Lightning payments through Boltz swaps for Arkade wallets. It creates and pays Lightning invoices, gets Lightning swap fees and limits, monitors pending/history of swaps, and manages swap-processing resources. The declared description is substantially broader, claiming Bitcoin send/receive over Arkade offchain and onchain plus stablecoin swaps. Those capabilities are not represented in this code chunk. While the declared description includes Lightning, it inaccurately describes this specific skill chunk because key claimed capabilities are absent.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The CLI example shows passing a private key as a command-line argument, which is especially dangerous because command-line arguments are commonly exposed through shell history, process listings, audit logs, crash reports, and agent telemetry. In a cryptocurrency wallet skill, disclosure of the private key enables full compromise of funds, making this more dangerous than a generic secret-handling issue.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README instructs users to initialize the wallet with a raw private key in a CLI argument, which is highly sensitive because command-line arguments can be exposed through shell history, process listings, logs, screenshots, or agent transcripts. In a skill intended for agent integration, this is more dangerous because agents often capture, replay, or store command invocations automatically, increasing the chance of credential compromise and irreversible theft of funds.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README documents live fund-transfer, invoice-payment, and swap operations without any warning that they move real assets, may be irreversible, and can incur fees or route funds to attacker-controlled destinations if misused. In an agent-skill context this is especially risky because users may delegate execution to automation, making accidental or prompt-induced transfers more plausible.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill invokes package-managed commands and describes wallet initialization and transaction operations, but it declares no explicit tool scope or permissions. In an agent setting, missing scope boundaries can let the runtime expose broader capabilities than intended, increasing the chance of unintended environment access or unsafe execution paths.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
- `swap-to-stable` / `swap-to-btc` — executes a stablecoin swap
- `swap-claim` / `swap-refund` — claims or refunds a swap

Read-only commands (`address`, `balance`, `history`, `ln-invoice`, `ln-fees`, `ln-limits`, `ln-pending`, `swap-quote`, `swap-pairs`, `swap-status`, `swap-pending`, `boarding-address`) are safe to run without confirmation.

**Wallet initialization:** `init` creates a new private key stored at `~/.arkade-wallet/config.json` (permissions `0600`). All other commands require `init` to have been run first. The agent MUST inform the user and get confirmation before running `init` for the first time.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The quick-start flow uses npx/dlx to fetch and execute a package at runtime without a pinned version. This creates a supply-chain risk: a compromised latest release or dependency could be executed immediately in the user's environment, potentially alongside wallet operations.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The command npx -y -p @arkade-os/skill arkade ... installs and executes the package dynamically without version pinning. Because this skill handles real funds and key material indirectly, executing an unpinned remote package materially increases the impact of package compromise.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

This is another instance of unpinned dynamic package execution in the command examples. Repetition of this pattern normalizes insecure installation for users, making supply-chain compromise more likely to affect real fund transfers.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
71% confidence
Finding

The skill stores wallet state and private keys in a persistent local config file and supports pending payment/swap operations, which creates session persistence around financial credentials and transaction state. Persistence itself is expected for a wallet, but in an agent environment it raises the risk of later unauthorized use if the host, account, or file permissions are compromised.

Content

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

Lightning Network

bash
# Create a Lightning invoice to receive payment
arkade ln-invoice <amount-sats> [description]

# Example: Create invoice for 25,000 sats

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest says the skill can 'Swap USDC/USDT stablecoins,' but this CLI exposes a much broader stablecoin feature set including initiating swaps in both directions, claiming completed swaps, refunding failed swaps, checking status, and tracking pending swaps. Those are materially broader wallet/settlement operations than the top-level description communicates, especially because they reach into external chain settlement flows and lifecycle management.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

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.

Content

Scanner excerpt · cli/arkade.mjs (reported line 163)May include surrounding context.

js
onboard                      Move funds from onchain to offchain (Arkade)
  offboard <btc-address>       Move funds from offchain to onchain

  ln-invoice <amount> [desc]   Create a Lightning invoice
  ln-pay <bolt11>              Pay a Lightning invoice
  ln-fees                      Show Lightning swap fees
  ln-limits                    Show Lightning swap limits

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

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.

Content

Scanner excerpt · cli/arkade.mjs (reported line 619)May include surrounding context.

js
}

/**
 * Create a LendaSwapSkill with SQLite persistence for swaps and wallet data.
 * Stores data in ~/.arkade-wallet/lendaswap.db
 */
async function createLendaSwap() {

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The BTC-to-stablecoin swap command initiates an irreversible fund-moving operation immediately after parsing arguments, with no interactive confirmation, dry-run, or explicit risk acknowledgment. In an agent-integration context, this raises the chance of accidental or prompt-induced asset transfers to attacker-controlled addresses or wrong chains.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The stablecoin-to-BTC swap command also executes a value-bearing swap without any explicit warning or confirmation about consequences, fees, or destination semantics. Because this CLI is intended for agent use, a malicious or mistaken instruction could trigger a real transfer using the caller's configured wallet and EVM address context.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The package description advertises broad, high-risk financial capabilities such as sending/receiving Bitcoin, Lightning transfers, and stablecoin swaps without indicating any user-consent gating, confirmation requirements, transaction limits, or scope restrictions. In an agent skill context, vague authorization boundaries around money movement materially increase the risk of unintended or over-broad invocation leading to irreversible asset transfer.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
81% confidence
Finding

The skill metadata declares persistent local config/database paths under the user's home directory, indicating session or wallet-related state survives across runs. For a financial skill, persistent wallet/config state can amplify damage from misuse, stale authorization, credential leakage, or cross-session confusion if the agent accesses prior sensitive state without fresh user approval.

Content

Scanner excerpt · package.json (reported line 34)May include surrounding context.

json
"build:esm": "tsc -p tsconfig.esm.json --outDir dist/esm",
        "build:cjs": "tsc -p tsconfig.cjs.json --outDir dist/cjs",
        "build:types": "tsc -p tsconfig.json --outDir dist/types --emitDeclarationOnly",
        "format": "prettier --write src cli",
        "lint": "prettier --check src cli",
        "prepublishOnly": "pnpm run build"
    },

Static analysis

No suspicious patterns detected.