T09 · Insecure Skill Coding Practices
- Location
scripts/import-credentials.sh:73- Finding
Unvalidated Credential Archive Extraction Allows Arbitrary File Overwrite
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
scripts/import-credentials.sh:73Unvalidated Credential Archive Extraction Allows Arbitrary File Overwrite
templates/docker-compose-watchonly.yml:31Production Watch-Only Deployment Co-Locates the Private-Key Signer with the Agent Node
templates/docker-compose-watchonly.yml:36Signer and Wallet Administrative APIs Are Published on All Host Interfaces
scripts/import-credentials.sh:102Full-Privilege Signer Admin Macaroon Is Required and Duplicated into the Agent Container
scripts/create-wallet.sh:224Standalone Wallet Seed and Unlock Passphrase Are Stored Together in Plaintext
scripts/install.sh:91Docker Images and Source Releases Are Executed Without Cryptographic Integrity Verification
templates/docker-compose-regtest.yml:40Regtest Bitcoin RPC Uses Public Fixed Credentials and Unrestricted Binding
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
| 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 |
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.
| 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:**
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
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.
# 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
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.
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.
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.
# 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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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=""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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=""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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=""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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=""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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=""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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=""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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=""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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=""
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.
No suspicious patterns detected.