Back to skill

Security audit

Lnd

Security checks for vulnerabilities and agentic risk

Overview

The skill is for running a Lightning node, but its production path exposes wallet and signing authority in ways that could put real funds at risk.

Use this only for disposable testnet, signet, or regtest setups unless you harden it first. For real funds, keep the signer on a separate secured host, bind admin APIs to localhost or an internal network only, replace admin macaroons with least-privilege signing credentials, avoid plaintext seed/passphrase storage, validate credential archives before extraction, and pin or verify all images and source releases.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (7)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/import-credentials.sh:73
Finding

Unvalidated Credential Archive Extraction Allows Arbitrary File Overwrite

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
templates/docker-compose-watchonly.yml:31
Finding

Production Watch-Only Deployment Co-Locates the Private-Key Signer with the Agent Node

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
templates/docker-compose-watchonly.yml:36
Finding

Signer and Wallet Administrative APIs Are Published on All Host Interfaces

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/import-credentials.sh:102
Finding

Full-Privilege Signer Admin Macaroon Is Required and Duplicated into the Agent Container

Content
View full analysis
&2 MISSING=true fi if [ "$MISSING" = true ]; then echo "" >&2 echo "Error: Credentials bundle is incomplete." >&2 echo "Expected: accounts.json, tls.cert, admin.macaroon" >&2 exit 1 fi # Set restrictive permissions on credential files. chmod 600 "$CREDS_DIR/accounts.json" chmod 600 "$CREDS_DIR/tls.cert" chmod 600 "$CREDS_DIR/admin.macaroon" echo "" # If a litd container is running, copy credentials into it so the # remotesigner config paths resolve inside the container. if command -v docker &>/dev/null; then for candidate in litd litd-shared; do if docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$candidate"; then docker exec "$candidate" mkdir -p /root/.lnd/signer-credentials docker cp "$CREDS_DIR/tls.cert" "$candidate:/root/.lnd/signer-credentials/tls.cert" docker cp "$CREDS_DIR/admin.macaroon" "$candidate:/root/.lnd/signer-credentials/admin.macaroon" docker cp "$CREDS_DIR/accounts.json" "$candidate:/root/.lnd/signer-credentials/accounts.json" ``` ### Technical Analysis The importer requires an `admin.macaroon` even though the Skill's own security guidance states that agents should not receive administrative macaroons in production. The macaroon is a bearer capability and is copied into both host storage and the watch-only container. Remote signing requires only signer-specific permissions. Requiring full administrative authority violates least privilege and increases the number of compromise locations. File mode `0600` does not protect the token from the owning agent account, root, Docker-capable processes, or compromise of the destination con ...[truncated 732 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/create-wallet.sh:224
Finding

Standalone Wallet Seed and Unlock Passphrase Are Stored Together in Plaintext

Content
View full analysis
"$PASSWORD_FILE" chmod 600 "$PASSWORD_FILE" echo "Passphrase saved to $PASSWORD_FILE (mode 0600)" echo "" # Copy password file into container if applicable. if [ -n "$CONTAINER" ]; then docker cp "$PASSWORD_FILE" "$CONTAINER:/root/.lnd/wallet-password.txt" echo "Password file copied into container." fi ``` ```bash # Store seed with restricted permissions on host. echo "$MNEMONIC" > "$SEED_OUTPUT" chmod 600 "$SEED_OUTPUT" echo "Seed mnemonic saved to $SEED_OUTPUT (mode 0600)" echo "" # Initialize wallet with password and seed. SEED_JSON=$(echo "$MNEMONIC" | jq -R . | jq -s .) PAYLOAD=$(jq -n \ --arg pass "$(echo -n "$PASSWORD" | base64)" \ --argjson seed "$SEED_JSON" \ '{wallet_password: $pass, cipher_seed_mnemonic: $seed}') ``` ### Technical Analysis Standalone mode writes both the master seed mnemonic and the wallet encryption passphrase as plaintext files under the same user-controlled directory. The password is additionally copied into the container. Unix mode `0600` only restricts access from other unprivileged local users. It does not protect against compromise of the owning account, root access, malware running as that user, Docker daemon access, insecure backups, or storage snapshots. Because both ...[truncated 785 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Error
Location
scripts/install.sh:91
Finding

Docker Images and Source Releases Are Executed Without Cryptographic Integrity Verification

Content
View full analysis
/dev/null || echo "") if [ -n "$LATEST_TAG" ]; then echo "Using latest tag: $LATEST_TAG" git checkout --quiet "$LATEST_TAG" else echo "Using HEAD (no tags found)." fi fi echo "" GOBIN=$(go env GOPATH)/bin # Build lnd. echo "Building lnd..." go build -tags "$BUILD_TAGS" -o "$GOBIN/lnd" ./cmd/lnd echo "Done." # Build lncli. echo "Building lncli..." go build -tags "$BUILD_TAGS" -o "$GOBIN/lncli" ./cmd/lncli ``` ```bash IMAGE="${LITD_IMAGE:-lightninglabs/lightning-terminal}" TAG="${VERSION:-${LITD_VERSION:-v0.16.0-alpha}}" echo "Image: $IMAGE:$TAG" echo "" # Pull the image. echo "Pulling image..." docker pull "$IMAGE:$TAG" echo "" # Verify the image works. echo "Verifying installation..." docker run --rm "$IMAGE:$TAG" litd --version 2>/dev/null || true ``` ### Technical Analysis Container images are referenced by mutable tags rather than immutable content digests. Source installation checks out a supplied tag or the repository's latest tag without verifying a signed release, expected commit hash, or checksum. Executing `litd --version` only confirms that the downloaded image runs; it does not verify its provenance or integrity. The command also executes the unverified artifact. Environment variables can override image names, further expanding the trust boun ...[truncated 850 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
templates/docker-compose-regtest.yml:40
Finding

Regtest Bitcoin RPC Uses Public Fixed Credentials and Unrestricted Binding

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (53)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The description centers on running Lightning services, but the skill also reads a wallet passphrase from disk and unlocks wallets via REST against local, containerized, or remote nodes. That materially increases the sensitivity of the skill because it moves from infrastructure setup into credential use and operational control over funds.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description centers on running Lightning services, but the skill also reads a wallet passphrase from disk and unlocks wallets via REST against local, containerized, or remote nodes. That materially increases the sensitivity of the skill because it moves from infrastructure setup into credential use and operational control over funds.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description centers on running Lightning services, but the skill also reads a wallet passphrase from disk and unlocks wallets via REST against local, containerized, or remote nodes. That materially increases the sensitivity of the skill because it moves from infrastructure setup into credential use and operational control over funds.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description centers on running Lightning services, but the skill also reads a wallet passphrase from disk and unlocks wallets via REST against local, containerized, or remote nodes. That materially increases the sensitivity of the skill because it moves from infrastructure setup into credential use and operational control over funds.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description centers on running Lightning services, but the skill also reads a wallet passphrase from disk and unlocks wallets via REST against local, containerized, or remote nodes. That materially increases the sensitivity of the skill because it moves from infrastructure setup into credential use and operational control over funds.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description centers on running Lightning services, but the skill also reads a wallet passphrase from disk and unlocks wallets via REST against local, containerized, or remote nodes. That materially increases the sensitivity of the skill because it moves from infrastructure setup into credential use and operational control over funds.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The description centers on running Lightning services, but the skill also reads a wallet passphrase from disk and unlocks wallets via REST against local, containerized, or remote nodes. That materially increases the sensitivity of the skill because it moves from infrastructure setup into credential use and operational control over funds.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The skill documents generating and storing a wallet passphrase and seed mnemonic on local disk. Even with 0600 permissions, local plaintext storage of wallet recovery material is highly sensitive; compromise of the host, backups, logs, or user account can expose funds and enable wallet takeover.

Content

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

md
2. Calls `/v1/genseed` to generate a 24-word seed mnemonic
3. Calls `/v1/initwallet` with the passphrase and seed
4. Stores credentials securely:
   - `~/.lnget/lnd/wallet-password.txt` (mode 0600)
   - `~/.lnget/lnd/seed.txt` (mode 0600)

### Unlock Wallet

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The documented file locations include plaintext wallet unlock material and seed backups under the user's home directory. Publishing stable credential paths increases discoverability for malware, other local users, or misconfigured backup/sync tooling, raising the risk of credential theft and fund loss.

Content

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

md
| Path | Purpose |
|------|---------|
| `~/.lnget/lnd/wallet-password.txt` | Wallet unlock passphrase (0600) |
| `~/.lnget/lnd/seed.txt` | 24-word mnemonic backup (0600, standalone only) |
| `~/.lnget/lnd/signer-credentials/` | Imported signer credentials (watch-only) |
| `versions.env` | Pinned container image versions |

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

The documentation identifies storage of the wallet unlock password and the 24-word seed in plaintext files under the agent user's home directory. Those two files are sufficient for full wallet recovery and spending, so any local compromise, same-user process access, backup leakage, or disk exfiltration can result in complete loss of funds.

Content

Scanner excerpt · references/security.md (reported line 42)May include surrounding context.

md
| File | Contents | Permissions |
|------|----------|-------------|
| `~/.lnget/lnd/wallet-password.txt` | Wallet unlock passphrase | 0600 |
| `~/.lnget/lnd/seed.txt` | 24-word BIP39 mnemonic | 0600 |

**This is suitable for:**

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/security.md (reported line 81)May include surrounding context.

md
wallet recovery.

2. **OS keychain:** Store the seed in the operating system's keychain (macOS
   Keychain, Linux Secret Service). Requires keychain unlock but survives
   disk inspection.

3. **Migrate to remote signer:** The recommended path. Use the

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

The script explicitly stores the wallet passphrase on disk in ~/.lnget/lnd/wallet-password.txt, and in standalone mode also stores the seed phrase in plaintext. Even with 0600 permissions, plaintext wallet secrets on disk materially increase the blast radius of local compromise, backups leakage, endpoint malware, or accidental exfiltration.

Content

Scanner excerpt · scripts/create-wallet.sh (reported line 25)May include surrounding context.

sh
#   standalone  — generates seed locally (keys on disk, less secure)
#
# Stores credentials at:
#   ~/.lnget/lnd/wallet-password.txt  (mode 0600)
#   ~/.lnget/lnd/seed.txt             (mode 0600, standalone mode only)

set -e

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

This line defines a fixed path for storing the wallet passphrase as a plaintext file, which is then used later in the workflow. In the context of a Lightning node, persistent local storage of wallet unlock material can allow unauthorized wallet access after host compromise and is especially risky because this skill handles financial assets.

Content

Scanner excerpt · scripts/create-wallet.sh (reported line 226)May include surrounding context.

sh
mkdir -p "$LNGET_LND_DIR"
chmod 700 "$LNGET_LND_DIR"

PASSWORD_FILE="$LNGET_LND_DIR/wallet-password.txt"
SEED_OUTPUT="$LNGET_LND_DIR/seed.txt"

# Generate or use provided passphrase.

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

Copying the plaintext password file into the container duplicates sensitive wallet unlock material and expands the number of locations from which it can be recovered. If the container filesystem, image layers, backups, or runtime environment are exposed, the wallet passphrase may be obtained by an attacker.

Content

Scanner excerpt · scripts/create-wallet.sh (reported line 245)May include surrounding context.

sh
# Copy password file into container if applicable.
if [ -n "$CONTAINER" ]; then
    docker cp "$PASSWORD_FILE" "$CONTAINER:/root/.lnd/wallet-password.txt"
    echo "Password file copied into container."
fi

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
else
        echo "Error: Profile '$PROFILE' not found." >&2
        echo "Available profiles:"
        ls -1 "$PROFILE_DIR"/*.env 2>/dev/null | xargs -n1 basename | sed 's/.env$//'
        exit 1
    fi
fi

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/docker-start.sh (reported line 135)May include surrounding context.

sh
else
        echo "Error: Profile '$PROFILE' not found." >&2
        echo "Available profiles:"
        ls -1 "$PROFILE_DIR"/*.env 2>/dev/null | xargs -n1 basename | sed 's/.env$//'
        exit 1
    fi
fi

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/start-lnd.sh (reported line 160)May include surrounding context.

sh
set -e

LNGET_LND_DIR="${LNGET_LND_DIR:-$HOME/.lnget/lnd}"
PASSWORD_FILE="$LNGET_LND_DIR/wallet-password.txt"
REST_PORT=8080
REST_HOST="localhost"
CONTAINER=""

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/unlock-wallet.sh (reported line 19)May include surrounding context.

sh
set -e

LNGET_LND_DIR="${LNGET_LND_DIR:-$HOME/.lnget/lnd}"
PASSWORD_FILE="$LNGET_LND_DIR/wallet-password.txt"
REST_PORT=8080
REST_HOST="localhost"
CONTAINER=""

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/unlock-wallet.sh (reported line 61)May include surrounding context.

sh
set -e

LNGET_LND_DIR="${LNGET_LND_DIR:-$HOME/.lnget/lnd}"
PASSWORD_FILE="$LNGET_LND_DIR/wallet-password.txt"
REST_PORT=8080
REST_HOST="localhost"
CONTAINER=""

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · templates/docker-compose-regtest.yml (reported line 76)May include surrounding context.

yaml
set -e

LNGET_LND_DIR="${LNGET_LND_DIR:-$HOME/.lnget/lnd}"
PASSWORD_FILE="$LNGET_LND_DIR/wallet-password.txt"
REST_PORT=8080
REST_HOST="localhost"
CONTAINER=""

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · templates/docker-compose-regtest.yml (reported line 100)May include surrounding context.

yaml
set -e

LNGET_LND_DIR="${LNGET_LND_DIR:-$HOME/.lnget/lnd}"
PASSWORD_FILE="$LNGET_LND_DIR/wallet-password.txt"
REST_PORT=8080
REST_HOST="localhost"
CONTAINER=""

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · templates/docker-compose-watchonly.yml (reported line 35)May include surrounding context.

yaml
set -e

LNGET_LND_DIR="${LNGET_LND_DIR:-$HOME/.lnget/lnd}"
PASSWORD_FILE="$LNGET_LND_DIR/wallet-password.txt"
REST_PORT=8080
REST_HOST="localhost"
CONTAINER=""

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · templates/docker-compose-watchonly.yml (reported line 51)May include surrounding context.

yaml
set -e

LNGET_LND_DIR="${LNGET_LND_DIR:-$HOME/.lnget/lnd}"
PASSWORD_FILE="$LNGET_LND_DIR/wallet-password.txt"
REST_PORT=8080
REST_HOST="localhost"
CONTAINER=""

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · templates/docker-compose.yml (reported line 30)May include surrounding context.

yaml
set -e

LNGET_LND_DIR="${LNGET_LND_DIR:-$HOME/.lnget/lnd}"
PASSWORD_FILE="$LNGET_LND_DIR/wallet-password.txt"
REST_PORT=8080
REST_HOST="localhost"
CONTAINER=""

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documents extensive shell-based operations that install software, start containers, manage wallets, and interact with remote services, but it declares no explicit tool scope or allowed-tools boundary. That omission increases the chance an agent is granted broader shell access than necessary, making accidental or unsafe command execution more likely in a high-risk financial context.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.