Skip to content

Instantly share code, notes, and snippets.

View echennells's full-sized avatar

Eric Chennells echennells

View GitHub Profile

Eric Chennells

Cybersecurity analyst and cloud computing consultant in Vancouver, BC.

What I do

  • Runlevel Security — independent cybersecurity consultancy. Security readiness and incident response for businesses and individuals: assessments against the CCCS baseline and CIS Controls, incident readiness, hardening (Microsoft 365, Linux, cloud, supply chain), personal security, and incident response. runlevelsecurity.com
  • Bitcoin L2s — I build on Spark and Lightning. sparkbtcbot is a self-custodial payments stack for AI agents: bitcoin in, gift cards out. yvrbtclabs.dev
  • Maker hardware — ESP32 sensor nodes, Meshtastic / LoRa mesh radios, click-together kits.
@echennells
echennells / disclosure.md
Created June 17, 2026 17:26
@bsv/wallet-toolbox — recipient substitution by a remote storage provider (disclosure record)

@bsv/wallet-toolbox — recipient substitution by a remote storage provider

Status: unpatched as of 2026-06-17.

Summary

BRC-100 wallets built on @bsv/wallet-toolbox can have outgoing payments redirected by their active remote storage provider. When createAction runs against a remote StorageClient, the storage server returns the transaction outputs to build; the wallet signs and broadcasts them without verifying that the recipient output scripts match what the caller requested. A malicious or compromised storage provider can substitute the recipient address, and the wallet UI continues to show the originally intended recipient.

Affected

  • @bsv/wallet-toolbox, @bsv/wallet-toolbox-client, @bsv/wallet-toolbox-mobile — current published versions; the affected code path is present at repository HEAD as of 2026-06-17.
  • Any BRC-100 wallet built on the toolbox while a remote storage provider is the active store.
# Libbitcoin Server configuration - testnet3
#
# A testnet3 node. The [database] buckets are sized for testnet3 scale (~5M
# blocks); body files preallocate modestly (~6 GB) and grow on demand toward the
# full ~230 GB testnet3 store. Chain identity matches chain::selection::testnet
# in libbitcoin-system. Initialize then run:
# bs -c testnet.cfg --newstore
# bs -c testnet.cfg
[log]
# Libbitcoin Server configuration - regtest
#
# A self-contained regtest node. Starts on ~40 MB of store (vs the ~177 GB
# mainnet default), isolated (no peers or seeds), serving the regtest chain at
# its genesis block. Chain identity matches chain::selection::regtest in
# libbitcoin-system. Initialize then run:
# bs -c regtest.cfg --newstore
# bs -c regtest.cfg
[log]
@echennells
echennells / libbitcoin-v4-testnet3-bugs.md
Last active May 18, 2026 23:21
libbitcoin v4 — issues observed during testnet3 sync from genesis

libbitcoin v4 — issues observed during testnet3 sync from genesis

Empirically reproduced on 2026-05-18 against upstream master a778552 (libbitcoin-server) and matching libbitcoin-system, libbitcoin-database, libbitcoin-network, libbitcoin-node master heads. Test environment: DigitalOcean droplet, Ubuntu 24.04, 8 vCPU, 32 GB RAM, 400 GB local SSD plus 500 GB attached block volume. Configuration: testnet3 selection, chain values taken verbatim from libbitcoin-system/src/settings.cpp's testnet section (genesis block, identifier 118034699, BIP9 bit0/bit1/bit2 active checkpoints, BIP30 deactivate checkpoint, BIP90 heights, checkpoints, milestone, minimum_work).

This writeup describes one consensus-rule mismatch and one configuration-driven resource-management issue. Both are required to be addressed before a testnet3 node can sync from genesis to tip on a host with bounded memory.


Issue 1 (consensus) — op_check_sig empty-key hard-fail at testnet3 height 471805

@echennells
echennells / gist:bf1f02151fb7c5a8847527a054b558be
Created February 1, 2025 22:00
Yours Wallet SPV Verification Problem
# Security Analysis: YoursWallet SPV Validation
## Summary
During security testing of YoursWallet, we discovered that despite claiming to implement Simplified Payment Verification (SPV), the wallet does not perform prop
er SPV validation of transactions. Through practical testing, we demonstrated that the wallet accepts fabricated transaction data without cryptographic verifica
tion.
## Technical Details
### Claimed Security Model
### WARNING ###
Mutiny stores your channel state in your browser cache as well as in a postgres database on your server. If you lose the state in one of the two locations it will resync, for example if you lose your browser
cache the next time you access mutiny it will sync from the postgres server. The opposite is also true. One issue with the self hosted mutiny is there isn't an easy way to handle the postgres backup, this is because
every time you do a lightning transaction the channel state is updated, and there isn't a way that I know of to trigger a postgres backup on each update to the database. If you accidently restore a previous version
of the channel state you will be in a bad place and possibly (almost certinaly, lose funds).
# update the machine (if you get an error about a lock just wait a few minutes and try again)
sudo apt update
@echennells
echennells / gist:b57577b501b88620195c51b544892b12
Created June 9, 2024 19:12
How to self-host mutiny wallet and use their signet
Build the https://github.com/MutinyWallet/mutiny-web docker container with the following environment variables:
# Add the ARG directives for build-time environment variables
ARG VITE_PROXY="/_services/proxy"
ARG VITE_STORAGE="/_services/vss/v2"
ARG VITE_SELFHOSTED="true"
ARG VITE_NETWORK="signet"
ARG VITE_ESPLORA="https://mutinynet.com/api"
ARG VITE_LSP="https://signet-lsp.mutinywallet.com"
ARG VITE_RGS="https://rgs.mutinynet.com/snapshot/"
# litd Log File
litd is logging to /var/log/syslog
Logrotate is a linux system utility that by default runs once per day, and will trim (rotate) your log files if configured to do so. It will also keep a configurable
number of previous log files but will compress them to save a considerable about of disk space. Compressed files have the .gz extension.
If once a day isn't frequent enough it can be configured to run as often as you'd like by editing the systemd logrotate.timer configuration. We won't cover that here,
and if once a day isn't enough you can also configure the verbosity level of the service that is being too chatty.
@echennells
echennells / inotify-channel-backup.md
Last active June 27, 2023 02:04 — forked from alexbosworth/inotify-channel-backup.md
Backup channel.backup file using systemd and inotify

LND backup script for channel.backup using inotify

Install inotify

sudo apt install inotify-tools

Create script to watch for changes and copy on change