Skip to content

[BUG] OpenNode callback accepts unauthenticated requests and never parses the webhook body #453

@Anshumancanrock

Description

@Anshumancanrock

Describe the bug

The /callbacks/opennode accepts any incoming request without verifying its authenticity. Every other callback handler (Zebedee, LNbits, Nodeless) validates the source , OpenNode is the only one that doesn't.

This has two problems:

  1. No HMAC check. OpenNode signs every webhook with a hashed_order field (HMAC-SHA256(api_key, charge_id)). The endpoint ignores it entirely.

  2. Wrong body parser. OpenNode sends webhooks as application/x-www-form-urlencoded (per their docs), but the route registers json() middleware only. The body is silently unparsed for real OpenNode requests, so even if validation were added, it would always operate on an empty object.

An attacker with a valid invoice ID can POST a fake status: paid payload and permanently corrupt that invoice's state in the database, making it uncompletable by the real payer.

To Reproduce

  1. Stand up the relay with OpenNode as the payment processor.
  2. Grab a valid invoice ID from the connection/invoice flow.
  3. Run:
curl -X POST https://<your-relay>/callbacks/opennode \
  --data "id=<invoice_id>&status=paid&order_id=<any_pubkey>&hashed_order=fakehash"
  1. Check the invoices table , status is now COMPLETED with no payment made.

Expected behavior

The endpoint should parse application/x-www-form-urlencoded bodies (as OpenNode sends them) and reject any request where hashed_order does not match HMAC-SHA256(OPENNODE_API_KEY, charge_id), which is what OpenNode's own documentation specifies and what the other handlers already do for their respective authentication schemes.

Screenshots

N/A

Metadata

Metadata

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions