Skip to content

v0.5.0 — persist the prompted passphrase; npm-script parity for the ceremonies

Choose a tag to compare

@echennells echennells released this 26 Aug 00:26
· 16 commits to main since this release

Security

  • Trail-of-Bits pass on the seed-binding work — 8 findings fixed before release. Two independent adversarial reviews (crypto/format + install/docs/reveal) ran against this batch; the crypto core survived every malleability and payload-edge-case attack, but the rollout had holes: (1) references/agent-class.md — the "drop-in" class users actually copy — still shipped the pre-seal env-only resolver, so someone who sealed a budget and followed the doc got no budget at all; (2) a sealed seed whose policy didn't reach the agent ran silently unbound — now the plaintext version byte is checked and a sealed-but-unbound wallet throws; the context also moved to globalThis (duplicate module copies) and a policy-less load can no longer clear an established one; (3) the seed header wasn't in the GCM AAD, so flipping 0x020x01 passed authentication and reinterpreted the payload as a bare mnemonic — v2 now authenticates the header (v1 untouched); (4) npx <cmd> does not fail closed — it fetches a registry package named after the command, and all five of our bin names were unregistered; docs now use npm exec --no, and both agent-facing rule files say to refuse any npx install offer; (5) the ceremonies read the passphrase from .env (which sits next to the wallet), reducing "requires the passphrase" to "requires a PTY" — they now always prompt; (6) the over-budget error told sealed-policy callers to edit .env, the exact move the seal neutralizes; (7) SIGTERM/SIGHUP skipped the seed-reveal screen wipe (the exit hook doesn't run for signals), leaving the mnemonic on screen indefinitely; (8) the reveal claimed "alternate buffer wiped" unconditionally, but GNU screen ships altscreen off — the message is now conditional and tells screen users to clear their scrollback. Also: README no longer teaches an unpinned SDK install, the pin-staleness tradeoff is stated, and npm@latest on Node 20 is corrected (engines are warn-only, so it installs npm 12 anyway — use npm@11). +12 regression tests.

  • Seed-bound spending policy (opt-in): the budget can now be sealed inside the encrypted seed. Guard enforcement used to depend on files the agent can write — rm ~/.spark/spend-ledger.json (or truncating it, or editing .env to drop SPARK_DAILY_BUDGET_SATS) silently restored the full budget; a cleanup command, a prompt injection, or a machine migration all failed open. Now npx sparkbtcbot-set-policy (user-run, TTY-gated) binds dailyBudgetSats into the encrypted seed payload (v2 seed format — reading it needs the passphrase, tampering fails the GCM tag, deleting it deletes the wallet: the agent can't remove the budget without removing the money), and the spend ledger becomes HMAC-signed with a seed-derived HKDF key (never the AES key). Under a bound policy, a missing / unsigned / edited ledger fails closed with instructions to run npx sparkbtcbot-reset-ledger — the passphrase-gated legitimate reset that finally makes reset distinguishable from attack (previously rm was both). A seed-bound budget wins over the env var absolutely. v1 seeds and env-var budgets are completely unchanged — no policy, no new behavior. Honest limits, documented: the bar moves from rm to executing code, not to impossibility; replay of a validly-signed old ledger is undefendable client-side; raw-SDK calls still bypass wrapper guards. New exports: loadSeedPayload(FromEnv), validateSeedPolicy, deriveLedgerHmacKey, initSignedLedger; new CLIs: sparkbtcbot-set-policy, sparkbtcbot-reset-ledger. 16 attack-first tests (each attack proven to throw).

Changed

  • Agents are explicitly told that running SETUP is allowed and expected. Live testing showed agents over-extending the reveal-mnemonic prohibition into refusing npm run setup when the user asked — citing rules the docs never contained (setup has not printed or written the mnemonic in plaintext since 0.4.0). AGENTS.md and SKILL.md now carry an affirmative rule: creating the wallet on the user's behalf is the designed flow; the only secret to guard during setup is the passphrase, which goes to .env and is never echoed.