Back to skill

Security audit

Bitcoin and Tether on Arkade

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real cryptocurrency wallet and swap integration, but it has review-worthy safety gaps around private-key handling, irreversible payments, and mutable package execution.

Review this carefully before installing. Use only small test amounts, pin exact package versions, do not paste any real private key into a shell command, protect or avoid the ~/.arkade-wallet/config.json hot-wallet file, and require explicit human approval for send, offboard, Lightning pay, and swap actions.

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 (4)

T09 · Insecure Skill Coding Practices

Warning
Location
src/skills/lendaswap.ts:58
Finding

<![CDATA[Custom LendaSwap endpoints can receive API credentials and financial metadata]]>

Content
View full analysis
{ const url = `${this.apiUrl.replace(/\/$/, "")}${path}`; const headers: Record = { "Content-Type": "appl ...[truncated 2654 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
README.md:50
Finding

<![CDATA[README instructs users to place a private key in process arguments while the CLI interprets it as a server URL]]>

Content
View full analysis
``` It repeats the same contract in the command table: ```markdown | `init [url]` | Initialize wallet | ``` The actual CLI treats the first argument as a server URL: ```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); const { sdk } = await getSDK(); const { Wallet, SingleKey } = sdk; const wallet = await Wallet.create({ identity: SingleKey.fromHex(config.privateKey), arkServerUrl: config.serverUrl, }); const address = await wallet.getAddress(); console.log("Wallet initialized successfully!"); console.log(`Server: ${config.serverUrl}`); console.log(`Address: ${address}`); } catch (e) { console.error(`Error: Failed to initialize wallet: ${e.message}`); process.exit(1); } } ``` ```javascript switch (command) { case "init": await cmdInit(args[1]); break; ``` ### Technical Analysis Private keys are bearer secrets that must not be passed through command-line arguments. Command arguments may be retained in shell history, term ...[truncated 1866 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
cli/arkade.mjs:35
Finding

<![CDATA[Wallet spending key is persisted as unencrypted JSON]]>

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:31
Finding

<![CDATA[Quick-start instructions execute mutable, unpinned packages]]>

Content
View full analysis
Remediation
View remediation
add arkade-os/skill ``` 3. Prefer installation into a project with a committed lockfile over repeated ephemeral package execution. 4. Publish package provenance and signed release artifacts where supported. 5. Use registry integrity verification and monitor publisher accounts for unauthorized releases. 6. Review transitive dependency changes before upgrading versions used for wallet operations. 7. Run installation and build steps in a restricted environment without access to wallet keys or production credentials. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (38)

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 110)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 371)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

Missing User Warnings

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README instructs users to initialize a wallet with a raw private key hex value but provides no warning about secret handling, storage, shell history leakage, or process-list exposure. In a cryptocurrency wallet context, mishandling a private key can lead directly to irreversible theft of funds, making this materially dangerous documentation.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README demonstrates commands for sending Bitcoin and paying Lightning invoices without warning that these are real value-transfer operations that may be irreversible if the destination or amount is wrong. Because this skill is specifically for financial transactions, omission of safety guidance increases the chance of accidental loss by users or downstream agents automating these commands.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The Bitcoin-related portion of the description is accurately represented by the code: it supports Arkade offchain send/receive, onchain receive via boarding + onboard, and onchain payment via offboard, along with balance/history/incoming-funds helpers. However, the declared purpose also says the skill swaps USDC/USDT stablecoins, and there is no code for stablecoin handling, swapping, token balances, or related ramp logic. This is a material description-behavior mismatch due to an overclaimed capability.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied code chunk does not implement general Bitcoin send/receive features, onchain onboarding/offboarding, or Lightning operations. Instead, it is narrowly focused on BTC↔stablecoin swaps through the LendaSwap API for Arkade wallets. The stablecoin swap portion of the description is consistent, but the broader declared description materially overstates the skill's capabilities and primary purpose relative to this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The implementation is narrowly focused on Lightning payments using Boltz swaps. It supports receiving via reverse swaps, sending via submarine swaps, fee/limit queries, pending/history retrieval, and swap manager lifecycle methods. The declared description is broader, claiming onchain Bitcoin transfers, Arkade offchain send/receive, and stablecoin swaps. Those capabilities are not represented in this supplied code chunk. While the Lightning portion of the description is accurate, the overall description overstates what this chunk actually does, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill enables irreversible cryptocurrency transactions, wallet initialization, and onchain/offchain fund movement but does not prominently warn users about financial risk, finality, network fees, or the need to verify destination addresses. In an autonomous or semi-autonomous agent context, lack of explicit warnings increases the chance of accidental fund loss.

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
87% confidence
Finding

The command list includes onboarding, offboarding, and swapping operations that move assets across systems and chains, but it does not warn about finality, fees, address mistakes, or bridge/swap-specific risks. In this financial skill context, such omissions can contribute to user error and irreversible asset loss even if the commands are legitimate features.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill documents commands and SDK usage that require network access and local secret storage, but it declares no explicit tool scope or permissions. In an agent environment, this can cause the skill to run with broader-than-expected capabilities or without clear operator review of network and filesystem access.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The activation rule user wants to send or receive Bitcoin is broad enough to trigger this skill for generic Bitcoin tasks, even when the user did not ask to use Arkade. In an agent setting, overbroad routing is dangerous because this skill can create addresses, persist wallets, and initiate payment-related operations tied to a specific third-party service.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The trigger user wants to use Lightning Network is too general and could route unrelated Lightning tasks into a skill that depends on Arkade and Boltz swap flows. Misrouting users into a financial skill can expose them to unwanted wallet creation, incorrect payment rails, or irreversible payment attempts.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

Using npx/dlx to fetch and execute an unpinned package runs whatever version is currently published at install time. If the package or one of its dependencies is compromised, users may execute attacker-controlled code with access to wallet files, network connectivity, and payment flows.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding

The command npx -y -p @arkade-os/skill pulls and executes the latest published package without version pinning. For a cryptocurrency skill that stores keys locally and can initiate payments, this materially increases supply-chain risk and the blast radius of a package compromise.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding

This is another unpinned dynamic execution example that can cause users to run a newly published or hijacked package version. Because the skill interacts with private keys and irreversible Bitcoin and Lightning transactions, a supply-chain compromise could directly lead to theft of funds.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
72% confidence
Finding

The skill persists wallet configuration and auto-generated private keys in a local config file, creating session persistence of sensitive credentials. If file permissions are weak, the host is multi-user, or another process can access the home directory, an attacker could recover keys and drain funds.

Content

Scanner excerpt · SKILL.md (reported line 125)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

Session Persistence

Medium
Category
Rogue Agent
Confidence
91% confidence
Finding

The wallet is auto-initialized and the generated private key is persisted to disk in a long-lived config file under the user's home directory. Even with restrictive file permissions, persistent storage of an unencrypted hot-wallet secret increases the blast radius of local compromise, malware, backups, or accidental file exposure.

Content

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

js
}

/**
 * Create wallet from config, auto-initializing if needed.
 */
async function createWallet() {
  let config = loadConfig();

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

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest says the skill can 'Swap USDC/USDT stablecoins,' but the top-level file documentation initially advertises only 'swap-quote' and 'swap-pairs' in the module usage block, while the actual CLI help and command dispatcher implement full execution and status commands for stablecoin swaps, including swap-to-stable, swap-to-btc, swap-status, and swap-pending. This means the code performs broader state-changing swap operations than the file's earlier documented command list suggests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The Lightning payment path performs a real funds-moving action immediately after accepting a BOLT11 invoice, with no confirmation prompt, decoded invoice preview, amount verification, or destination summary. In an agent-integrated CLI, that increases the risk of accidental or socially engineered payments because untrusted input can directly trigger value transfer.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.