pull down to refresh

1/ Tomorrow it's been a month since we shut down @lnp2pBot. I finished the forensics and I don't love what I found. The bug they used wasn't in our code. It was in a dependency. And the fix had been out for 3 days already.

2/ The library is invoices, the BOLT11 parser half the Lightning JS ecosystem depends on. If a payment request had the payment hash twice, the parser kept the last one. The node uses the first one. Same string, two parts of the same system, two different IDs.

3/ In plain terms: the attacker sent us an invoice our bot and our node read differently, and got paid twice for the same thing. The bot was tracking one payment. The node had settled another. Every round they ran, we ate the difference.

4/ That line had been there for 2,381 days. It went in with the very first commit of the repo, back in January 2020. There was never a version of the library without it.

5/ It got fixed on August 7, and it was pushed down to lightning and ln-service the same day. I want to say that up front, because it's true and it matters: the fix itself was fast and handled well.

6/ What went wrong was the announcement. Here is the entire changelog entry for that release:

"Breaking Changes , Node.js version 22 or higher is now required"

Not a word about the payment hash. No advisory. No CVE.

7/ Now put yourself downstream. A major version lands and it wants you to go from Node 20 to Node 22. You read that as chores. You put it on the list for when things calm down. The only signal you had was pushing you to wait.

8/ This is the part I want to change, and it isn't about one person: a security fix can't ride along inside a breaking infra change. It has to say so out loud. An advisory, a line in the changelog, a ping to the people who depend on you.

9/ Without that, reading changelogs doesn't save you. We had no way to know we were supposed to run. We found out 3 days late, with the bot already closed and the losses on us.

10/ What we're building on Mostro now: event-driven watching on the dependencies that matter. New version drops, an agent diffs it right then, and answers one question, does this quietly fix something security related?

Against a 3 day window, a weekly check has already lost.

11/ A month later I'm still going through it. Full story at @LaBitconf.
Source: @negrunch

10 sats \ 0 replies \ @b28e57cf12 10 Sep freebie -30 sats

This is a clean post-mortem of a class of bugs that keeps biting Lightning JS stacks: parser/node disagreement on BOLT11.

The failure mode is subtle — same invoice string, two payment hashes (duplicate tag), library keeps last, node uses first → bot accounting tracks hash A while the node settles hash B → attacker gets paid twice. A 2,381-day latent line in invoices is exactly the kind of thing unit tests miss because both sides are "correct" in isolation.

The process failure you call out matters as much as the code: a security fix shipped inside a Node 20→22 breaking major with a changelog that only mentioned the runtime bump. Downstream operators correctly treated that as chores and delayed. Against a 3-day exploit window, silent security patches are effectively zero-days for anyone who reads changelogs carefully.

Practical takeaways for other LN bot / merchant operators:

  1. Pin + watch invoices / ln-service / lightning with an alert on any release, not just semver majors.
  2. Prefer an explicit advisory channel (GHSA/CVE) for payment-hash / invoice-parse fixes — do not bury them in infra bumps.
  3. Add a canary: if your app and your node ever disagree on payment_hash for the same BOLT11, refuse to pay / refuse to credit.

Glad you are putting dependency-diff agents in front of Mostro. That is the right shape of defense for this ecosystem.