Back to skill

Security audit

Sparkbtcbot

Security checks for vulnerabilities and agentic risk

Overview

This is a real Spark Bitcoin wallet skill, but it gives an agent full-control wallet access and allows autonomous fund movement without hard spending controls.

Use this only with REGTEST or a small, disposable hot wallet unless you add external controls. Do not give it a primary wallet mnemonic, do not run mnemonic-generating examples in logged or CI environments, and prefer the documented proxy or your own allowlists, approval gates, and hard spending limits for real funds.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:548
Finding

Unbounded Payment of Attacker-Controlled L402 Invoices

Content
View full analysis
s.name === "amount"); const amountSats = Math.ceil(Number(amountSection.value) / 1000); const payResult = await this.#wallet.payLightningInvoice({ invoice, maxFeeSats }); let preimage = payResult.paymentPreimage; // Poll if needed if (!preimage && payResult.id) { for (let i = 0; i < 15; i++) { await new Promise((r) => setTimeout(r, 500)); const status = await this.#wallet.getLightningSendRequest(payResult.id); if (status?.paymentPreimage) { preimage = status.paymentPreimage; break; } if (status?.status === "LIGHTNING_PAYMENT_FAILED") throw new Error("Payment failed"); } } if (!preimage) throw new Error("No preimage received"); // Retry with auth ...[truncated 2873 chars]
Remediation
View remediation
maxPaymentSats) { throw new Error( `L402 invoice amount ${amountSats} exceeds limit ${maxPaymentSats}`, ); } ``` 2. Require explicit user approval showing the destination, invoice amount, routing-fee cap, and total maximum cost unless a separately configured policy authorizes that exact domain and amount. 3. Maintain per-transaction, per-domain, and cumulative daily spending limits outside the model-controlled request parameters. 4. Permit only HTTPS destinations and enforce an allowlist of trusted hostnames. Reject embedded credentials, nonstandard schemes, private-network addresses where unnecessary, and unexpected ports. 5. Disable automatic redirects or validate every redirect target. Ensure the final endpoint receiving the macaroon and preimage is the same authorized origin that issued the challenge. 6. Validate the decoded invoice thoroughly, including amount presence, amount bounds, expiry, network, and expected payee where available. 7. Preview the L402 cost before payment and bind the approved challenge to the subsequent payment operation to prevent challenge substitution. 8. Use the documented scoped wallet proxy for production so that the agent never receives unrestricted mnemonic access and server-side controls can enforce revocable credentials, roles, audit logging, and spending caps. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
examples/wallet-setup.js:35
Finding

Generated Wallet Mnemonic Is Written to Plaintext Process Output

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (25)

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: sparkbtcbot
description: Set up Spark Bitcoin L2 wallet capabilities for AI agents. Initialize wallets from mnemonic, transfer sats and tokens, create/pay Lightning invoices, pay L402 paywalls, manage deposits and withdrawals. Use when user mentions "Spark wallet," "Spark Bitcoin," "BTKN tokens," "Spark L2," "Spark SDK," "Spark payment," "Spark transfer," "Spark invoice," "L402," "Lightning paywall," or wants Bitcoin L2 capabilities for an agent.
argument-hint: "[Optional: specify what to set up - wallet, payments, tokens, lightning, l402, or full]"
requires:
  env:
    - name: SPARK_MNEMONIC
      description: 12 or 24 word BIP39 mnemonic for the Spark wallet. This is a secret key that controls all funds — never commit to git or expose in

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 · examples/balance-and-deposits.js (reported line 42)May include surrounding context.

js
.toString()}`);
    }
  } else {
    console.log("\nNo token balances.");
  }

  // Generate deposit addresses
  console.log("\n=== Deposit Addresses ===");

  const staticAddr = await wallet.getStaticDepositAddress();
  console.log("Static (reusable):", staticAddr);

  const singleAddr = await wallet.getSingleUseDepositAddress();
  console.log("Single-use:       ", singleAddr);

  console.log("\nSend BTC to either address. Deposits need 3 L1 confirmations.");
  console.log("After confirmation, claim with:");
  console.log('  wallet.claimStaticDeposit({ transactionId: "txid", ... })');

  // List recent transfers
  const { transfers } = await wallet.getTransfers(5, 0);
  if (transfers.length > 0) {
    console.log("\n=== Recent Transfers ===");
    for (const tx of transfers) {
      console.log(`  ${tx.id}: ${tx.totalValue} sats [${tx.status}]`);
    }
  } else {
    console.log("\nNo transfers yet.");
  }

  wallet.cleanupConnections();
}

main().catch((err) => {
  console.error("Err

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 · examples/spark-agent.js (reported line 205)May include surrounding context.

js
.toString()}`);
    }
  } else {
    console.log("\nNo token balances.");
  }

  // Generate deposit addresses
  console.log("\n=== Deposit Addresses ===");

  const staticAddr = await wallet.getStaticDepositAddress();
  console.log("Static (reusable):", staticAddr);

  const singleAddr = await wallet.getSingleUseDepositAddress();
  console.log("Single-use:       ", singleAddr);

  console.log("\nSend BTC to either address. Deposits need 3 L1 confirmations.");
  console.log("After confirmation, claim with:");
  console.log('  wallet.claimStaticDeposit({ transactionId: "txid", ... })');

  // List recent transfers
  const { transfers } = await wallet.getTransfers(5, 0);
  if (transfers.length > 0) {
    console.log("\n=== Recent Transfers ===");
    for (const tx of transfers) {
      console.log(`  ${tx.id}: ${tx.totalValue} sats [${tx.status}]`);
    }
  } else {
    console.log("\nNo transfers yet.");
  }

  wallet.cleanupConnections();
}

main().catch((err) => {
  console.error("Err

Known Vulnerable Dependency: protobufjs==7.5.4 — 12 advisory(ies): CVE-2026-44294 (protobuf.js: Denial of service from crafted field names in generated code); CVE-2026-44293 (protobuf.js: Code injection through bytes field defaults in generated toObject c); CVE-2026-44289 (protobuf.js: Denial of service through unbounded protobuf recursion) +9 more

Critical
Category
Supply Chain
Confidence
98% confidence
Finding

protobufjs 7.5.4 is present with multiple serious advisories including denial of service and potential code-injection issues in generated conversion/codegen paths. This is highly concerning for a payment/wallet skill because protobuf is used in gRPC-based communications and attacker-controlled messages may traverse these parsers, raising both availability and potentially integrity risks depending on how code generation/utilities are used.

Content

No source excerpt is available for this finding.

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
80% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

Scanner excerpt · BUGFIX-tokenBalances-map.md (reported line 31)May include surrounding context.

md
## Why this is especially bad for AI agents

AI agents (the target users of this skill) generate code on the fly. They default to the most common JS patterns — `JSON.stringify`, `Object.entries`, `Object.keys`. All of these work on plain objects but silently produce empty results on Maps. There's no error, no warning, no indication that data was lost.

An agent could:
- Report zero token balance when the user actually holds tokens

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The withdraw method sends funds to an on-chain address, an irreversible operation with direct impact on user assets. There is no confirmation prompt, warning message, or inline documentation disclosing the risk before the withdrawal is executed.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The script prints a newly generated wallet mnemonic directly to stdout and also prints a ready-to-paste SPARK_MNEMONIC=... line for a .env file. A wallet mnemonic is the root secret for the Bitcoin L2 wallet, so exposing it in terminal output, logs, CI traces, shell history, or shared screenshots can allow full wallet takeover and irreversible asset theft.

Content

Scanner excerpt · examples/wallet-setup.js (reported line 37)May include surrounding context.

js
if (mnemonic) {
    console.log("\n=== SAVE THIS MNEMONIC SECURELY ===");
    console.log(mnemonic);
    console.log("\n=== Add to .env ===");
    console.log(`SPARK_MNEMONIC=${mnemonic}`);
    console.log(`SPARK_NETWORK=${network}`);
  }

Known Vulnerable Dependency: @grpc/grpc-js==1.14.3 — 2 advisory(ies): CVE-2026-48068 (@grpc/grpc-js: A malformed request can cause a server crash); CVE-2026-48069 (@grpc/grpc-js: An incoming malformed compressed message can cause a client or se)

High
Category
Supply Chain
Confidence
96% confidence
Finding

The lockfile pins @grpc/grpc-js 1.14.3, and the cited advisories indicate malformed gRPC traffic can crash a server or endpoint processing compressed messages. Because this skill depends on networked wallet/payment infrastructure and transitively uses gRPC libraries, a reachable vulnerable parser can create denial-of-service conditions against agent payment operations.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
95% confidence
Finding

ws 8.19.0 is present with advisories for memory disclosure and memory exhaustion through fragmented frames/chunks, which are legitimate network-facing concerns. Because this skill depends on real-time wallet/payment infrastructure and includes WebSocket-capable dependencies, exploitation could disrupt service or leak process memory in environments where WebSocket connections are exposed.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill requests access to a highly sensitive environment variable (SPARK_MNEMONIC) but does not declare an explicit tool scope or permission boundary. In a skill that can initiate payments and withdrawals, missing explicit scope increases the risk of overbroad secret exposure and unsafe invocation by downstream agents.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
97% confidence
Finding

The skill explicitly enables autonomous invocation for sending and receiving Bitcoin payments without human approval for each transaction. Because the same skill holds the mnemonic granting full custody, any prompt injection, agent compromise, or logic error could trigger irreversible fund transfers.

Content

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

md
description: Network to connect to (MAINNET or REGTEST)
      default: MAINNET
model-invocation: autonomous
model-invocation-reason: This skill enables agents to autonomously send and receive Bitcoin payments. Autonomous invocation is intentional — agents need to pay invoices and respond to incoming transfers without human approval for each transaction. Use spending limits and the proxy for production environments where you need guardrails.
homepage: https://sparkbot.yvrbtclabs.dev
---

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

md
AI agents that transact need a monetary network that matches their nature: programmable, borderless, and available 24/7 without gatekeepers. Bitcoin is that network.

- **Hard-capped supply** — 21 million coins is the protocol-enforced ceiling. An agent accumulating value doesn't lose it to monetary expansion.
- **No account required** — There's no sign-up, no identity verification, no approval process. Generate a key and you're on the network. This matters for autonomous agents that can't fill out forms or wait for human review.
- **Irreversible settlement** — Once confirmed, transactions cannot be reversed by a third party. Agents don't need to handle chargebacks or payment disputes.
- **Open infrastructure** — The protocol is open source, the network is public, and the fee market is transparent. Agents can audit their own transaction costs and verify their own balances without trusting an intermediary.
- **Proven reliability** — The network has operated continuously since 2009 without a single successful attack on the base protocol, securing over $1 trillion in value.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 871)May include surrounding context.

md
const { agent } = await SparkAgent.create(process.env.SPARK_MNEMONIC);

// Check cost first
const preview = await agent.previewL402("https://api.example.com/paid-endpoint");
console.log("Cost:", preview.amountSats, "sats");

// Pay and fetch

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The fetchL402 flow can automatically pay a Lightning invoice from an arbitrary external URL and then send an authorization token back to that service, enabling unreviewed outbound payments to third parties. In combination with autonomous invocation and full wallet custody, this creates a direct path for an agent to spend real funds on attacker-controlled endpoints.

Content

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

md
console.log("Cost:", preview.amountSats, "sats");

// Pay and fetch
const result = await agent.fetchL402("https://api.example.com/paid-endpoint", {
  maxFeeSats: 10,
});
console.log("Paid:", result.paid, "Data:", result.data);

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The transfer method initiates a value transfer using the wallet SDK, which is a safety-critical and potentially irreversible action. There is no confirmation prompt, user-facing warning, or explanatory comment indicating that calling this method will move funds.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

payLightningInvoice directly pays a BOLT11 invoice, which can spend funds and may be difficult or impossible to reverse. The code provides no confirmation prompt, warning, or inline documentation alerting users to this consequence.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Both transferTokens and batchTransferTokens perform asset transfers, which are safety-critical operations affecting user balances. The file contains no confirmation prompt, visible warning, or explanatory note that these methods initiate irreversible token movements.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The demo prints a newly generated wallet mnemonic to stdout, which exposes the wallet's root secret material to anyone with terminal access, shell history capture, logs, CI artifacts, or process-output monitoring. In a wallet context, possession of the mnemonic can allow full recovery and theft of funds, so this is a real secret-disclosure issue despite being labeled demo code.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: @opentelemetry/core==2.5.0 — 1 advisory(ies): CVE-2026-54285 (OpenTelemetry Core: Unbounded memory allocation in W3C Baggage propagation)

Low
Category
Supply Chain
Confidence
88% confidence
Finding

@opentelemetry/core 2.5.0 is present and the advisory describes unbounded memory allocation during W3C Baggage propagation, which can enable resource exhaustion when processing attacker-controlled telemetry headers. In this wallet skill, the issue is less central than direct payment handling, but any exposed HTTP/gRPC boundary that propagates trace context could still be abused for degradation.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: @protobufjs/utf8==1.1.0 — 1 advisory(ies): CVE-2026-44288 (protobufjs has overlong UTF-8 decoding)

Low
Category
Supply Chain
Confidence
77% confidence
Finding

The lockfile includes @protobufjs/utf8 1.1.0, and the cited overlong UTF-8 decoding flaw is a legitimate dependency weakness. On its own this is typically lower impact, but it can undermine input validation assumptions in protobuf processing paths used by wallet/network APIs.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: bn.js==4.12.2 — 1 advisory(ies): CVE-2026-2739 (bn.js affected by an infinite loop)

Low
Category
Supply Chain
Confidence
82% confidence
Finding

bn.js 4.12.2 is present through elliptic, and the advisory indicates crafted input may trigger an infinite loop, causing denial of service. In a Bitcoin wallet context, cryptographic and parsing libraries may process untrusted keys, signatures, or transaction-related values, so availability impact is relevant even if direct code execution is unlikely.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: elliptic==6.6.1 — 1 advisory(ies): CVE-2025-14505 (Elliptic Uses a Cryptographic Primitive with a Risky Implementation)

Low
Category
Supply Chain
Confidence
80% confidence
Finding

elliptic 6.6.1 is a real flagged dependency and is especially notable in a Bitcoin-related skill because elliptic-curve operations are security-sensitive. The cited issue is rated low, but risky cryptographic implementations can weaken assurances around signature/key handling or enable edge-case failures under attacker-controlled inputs.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ua-parser-js==2.0.8 — 1 advisory(ies): CVE-2026-48125 (UAParser.js: Unbounded `Sec-CH-UA-Model` parsing can trigger ReDoS in `withClien)

Low
Category
Supply Chain
Confidence
75% confidence
Finding

ua-parser-js 2.0.8 is present and the advisory describes a ReDoS condition from attacker-controlled client hint parsing. In this skill it appears transitive and peripheral to core wallet operations, so the main effect would likely be request handling slowdown or resource consumption rather than compromise of funds.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The dependency uses a caret range, which permits automatic adoption of newer minor/patch releases. That increases supply-chain risk because a compromised upstream release or breaking behavioral change could be pulled in without explicit review, which is especially sensitive here because the package handles Bitcoin wallet and payment capabilities.

Content

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

json
"type": "module",
  "description": "Claude Code skill for setting up Spark Bitcoin L2 wallet capabilities for AI agents",
  "dependencies": {
    "@buildonspark/spark-sdk": "^0.5.8",
    "dotenv": "^16.4.7"
  },
  "scripts": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
84% confidence
Finding

The dotenv dependency is also specified with a caret range, allowing unreviewed updates to be installed. While dotenv itself is less security-sensitive than the wallet SDK, any third-party dependency can become a supply-chain entry point if a malicious or compromised release is published.

Content

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

json
"description": "Claude Code skill for setting up Spark Bitcoin L2 wallet capabilities for AI agents",
  "dependencies": {
    "@buildonspark/spark-sdk": "^0.5.8",
    "dotenv": "^16.4.7"
  },
  "scripts": {
    "example:setup": "node examples/wallet-setup.js",