SECURITY
Nothing to sweep.
SatBooth assumes its public server will be attacked, so it gives that server almost nothing worth stealing. This is what it holds on each rail, and what an attacker gets.
If the public server is fully compromised
On-chain bitcoin
What the server holds
A watch-only descriptor (an xpub). No private keys.
What an attacker gets
The attacker sees addresses and payments.
Spends nothing.
Monero
What the server holds
The wallet’s primary address, and a login to a view-only wallet (address and private view key) in monero-wallet-rpc on a private host. No spend key anywhere.
What an attacker gets
The attacker sees incoming payments. Through the login it can read the view key and fake payments to SatBooth.
Spends nothing.
Lightning
What the server holds
Scoped Nostr Wallet Connect (NWC) connections to a small, dedicated Alby Hub, with a spending budget the hub enforces.
What an attacker gets
Losses are capped by the hub’s channel size and the payout budget, both small by design.
Capped, not zero.
The color of a card is never the only signal. Each ends in a plain verdict: spends nothing, or capped, not zero.
The trust boundary
Fig. 1 · where the money can and cannot go
01 · ANYONE
Customer
pays in sats, BTC or XMR on the checkout page
02 · PUBLIC HOST · faces the internet
SatBooth
- watch-only xpub · no keys
- view-only Monero login · no spend key
- scoped NWC link · budgeted
03 · HUB HOST · separate machine
Small Lightning hub
small channels, a hub-enforced payout budget, swept regularly to your main node or cold storage
The hub runs on a different host from the public service. That separation is a requirement: the Lightning bound holds only with it. The public host reaches the hub’s relay, bitcoind and wallet-rpc over a private link that you provide. The hub’s admin page, which controls its funds, is not on that link: you reach it through an SSH tunnel.
Received Lightning funds are swept regularly from the small hub to your main node or cold storage. SatBooth has no connection that can sweep. It alerts when the hub’s balance goes over its sweep threshold.
What an attacker still gets
- Your data. Addresses, payment history and order metadata. SatBooth keeps these minimal: invoice descriptions carry an opaque order id, never a user id or an email.
- Control of the order records. SatBooth writes its own ledger, so a compromised server can write false records, such as an order reported as paid that was not. Your own wallets show what really arrived.
- Its login to bitcoind. That user is limited to twelve methods, none of which sends money. The limit is per method, not per wallet, so the bitcoind SatBooth reaches must hold no wallet with private keys. The deployment bundle runs a dedicated bitcoind for that reason.
- Its login to the view-only wallet. It can point the wallet at a daemon the attacker runs, which is how payments get faked, and it can read the view key. It cannot sign anything.
What this does not cover. A timing or cache attacker on the same host is out of scope, so SatBooth belongs on a host you do not share. And the bounds above hold for the design as built: nothing has run on mainnet yet. The qualification report says what the regtest suite measured.
The habits that back it up
- Secrets never appear in argv, logs or API responses, not even redacted.
- On Linux the service locks its memory and disables core dumps and ptrace before it loads a key, so keys do not reach swap or a dump.
- The merchant API is on a private listener the bundle does not publish. Only the checkout page is public.
- The checkout page has no JavaScript and runs under a strict content security policy.
- Every limit that protects the hub or the money is global, so a flood of new accounts cannot stop paying customers.
- Webhooks are signed with an HMAC over a timestamp and the body, and an event is only a hint: your app reads the order.
- Releases are signed tags, and the images are reproducible and attested. See how to verify them.
The threat model lists every attack considered, what the design assumes, and where it stops.