Back to skill

Security audit

Alby Lightning Payments

Security checks for vulnerabilities and agentic risk

Overview

This Lightning payments skill is mostly purpose-aligned, but it includes under-disclosed live wallet operations that can move real funds, including through the package test command.

Review before installing. Use only a dedicated Alby NWC connection with strict spending limits, do not run npm test, and treat ALBY_NWC_URL as a wallet-spending secret. The undocumented scripts/wallet.js should be removed or made non-spending before trusting this package in an agent workflow.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/wallet.js:7
Finding

Live Wallet Operations Are Executed by the Package Test Command

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
send_sats.mjs:58
Finding

LNURL Requests Can Reach Private Networks Through DNS Resolution or Rebinding

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
send_sats.mjs:20
Finding

Payment Amounts Use Unsafe Floating-Point Integer Conversion

Content
View full analysis
lnurlData.maxSendable) { throw new Error(`Amount too high: maximum is ${lnurlData.maxSendable / 1000} sats`); } ``` `send_sats.mjs:139-143`: ```js // 5. Verify invoice amount matches requested amount (prevents overpayment by malicious server) const invoiceMsats = decodeBolt11Msats(invoiceData.pr); if (invoiceMsats !== null && invoiceMsats !== BigInt(msats)) { throw new Error( `Invoice amount mismatch: expected ${msats} msats, got ${invoiceMsats} msats. Aborting.` ); } ``` ### Technical Analysis The script confirms that the amount consists only of decimal digits but does not impose a maximum length or value before converting it to a JavaScript `Number`. JavaScript numbers use IEEE-754 double-precision floating point and cannot exactly represent every integer above `Number.MAX_SAFE_INTEGER`. Large values can therefore be rounded during `Number(amountArg)`. Multiplication by 1,000 can introduce further loss of precision. Extremely large digit strings can become `Infinity`. The later conversion `BigInt(m ...[truncated 1747 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script initiates real outgoing Lightning payments programmatically via both invoice payment and Lightning address payment with no confirmation, authorization gate, recipient validation, or spending limit. In an agent or automation context, this can directly cause unauthorized fund transfers if the script is triggered unexpectedly, supplied attacker-controlled payment details, or run with a wallet that has available balance.

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

Installation

bash
mkdir -p ~/.openclaw/workspace/skills/alby-lightning
cd ~/.openclaw/workspace/skills/alby-lightning
npm init -y
npm install @getalby/sdk

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

Installation

bash
mkdir -p ~/.openclaw/workspace/skills/alby-lightning
cd ~/.openclaw/workspace/skills/alby-lightning
npm init -y
npm install @getalby/sdk

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script directly pays any BOLT11 invoice provided on the command line as soon as it is invoked, with no explicit confirmation, amount display, recipient verification, or policy check before funds are spent. In an agent/skill context, this is risky because upstream tooling or prompt-influenced input could cause unintended real-money payments to attacker-controlled invoices.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code accesses a sensitive credential-like value via process.env.ALBY_NWC_URL to establish wallet connectivity, but the file provides no user-facing disclosure beyond implementation details. Under the code-file criteria, sensitive environment-variable access should be flagged when there is no confirmation prompt, visible warning, or explanatory documentation in the file.

Content

No source excerpt is available for this finding.

Dynamic Request Target

Medium
Category
Server-Side Request Forgery
Confidence
60% confidence
Finding

Request target host is built from a dynamic or untrusted value. If the host is attacker-influenced, this enables SSRF to arbitrary internal or metadata endpoints.

Content

Scanner excerpt · send_sats.mjs (reported line 101)May include surrounding context.

js
try {
  // 1. Resolve lightning address → LNURL metadata
  const lnurlRes = await fetch(
    `https://${domain}/.well-known/lnurlp/${encodeURIComponent(user)}`,
    { redirect: "error", signal: AbortSignal.timeout(10_000) }
  );

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified with a caret range (^7.0.0), which allows automatic installation of future minor and patch releases. This creates supply-chain risk because a compromised upstream release or unexpected breaking/security-relevant behavior change could be pulled in without explicit review, which is particularly relevant here because the package handles Lightning wallet/payment functionality.

Content

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

json
"license": "MIT",
  "type": "module",
  "dependencies": {
    "@getalby/sdk": "^7.0.0"
  }
}