aboutsummaryrefslogtreecommitdiffstats
path: root/index.ts
Commit message (Collapse)AuthorAgeFilesLines
* security: drop the admin endpoint surface and land pending hardeningAdam Soltys2026-09-131-4/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Removes the admin-gated endpoints and the account flags they set, plus a batch of hardening that had accumulated uncommitted in the tree. These were deployed and verified together, so they land as one change. admin surface: - drop POST /hidepay, POST /unlimit and GET /users, their handlers, and the now-unused admin preValidation export - `unlimited` was only ever written, never read; `hidepay` only appeared in output projections. Both flags go, along with their whitelist, public-fields and type entries. request log: - redactBody now recurses. It only masked top-level keys, so a body that nests credentials one level down wrote them to the log in plaintext, and pin fields were not on the list at all. payments: - sendOnchain/build gate `aid` through requireAccount, so a caller can only spend from an account it owns - sendOnchain signs only a tx we composed, matched against a short-lived per-account build receipt - raise xpay retry_for to 60s; route-finding preferred a drained zero-fee hop and burned the whole budget on it. check()'s reversal window keeps its 2x margin. ecash / invoices / webhooks: - resolve a token's mint through the IP-pinning fetcher instead of plain fetch, closing an unauthenticated SSRF path into the internal network - reject non-positive amounts before the balance write - /sign requires the caller to own the address, rather than signing under any address the hot wallet controls - webhook delivery no longer disables TLS verification; the body carries the merchant's shared secret registration: - refuse a username the v3 registrar holds unless the caller's own nostr key is the holder (lib/names.ts) liquid: - honour the deposit kill switch at invoice generation and at credit elements image: - pin 23.3.4 and verify the release tarball checksum Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_0112TGi9GGNWqji1XQ5jZRzc
* fund: authenticated recovery of a rotated fund's old linkAdam Soltys2026-08-281-1/+1
| | | | | | | | | | | | | | | When a fund's secret id has been rotated (invalidating an exfiltrated id list), its old id 404s. Let a legit owner who bookmarked the old link find the fund again — but reveal the new id ONLY to an authenticated manager of the new fund, via a `fund:rotated:<oldid>` -> newid map. An anonymous caller or a non-owner gets the same "fund not found" as before, so an attacker replaying a leaked old id learns nothing (an open old->new redirect would defeat the rotation). The /fund/:id route now runs `optional` auth so req.user is available without requiring it; bearer funds with no managers are intentionally not recoverable this way. rotate-funds.ts records the mapping on any future rotation. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01DKkev76U4YRnRAqM6jqbae
* harden: remove debug /echo endpoint; widen LN health probe timeoutAdam Soltys2026-08-271-5/+0
| | | | | | | | | | | | | | | Remove the unauthenticated POST /echo route — a request-body reflector with no place in production; it served only to echo attacker probe payloads. Raise the health-check listener-backlog probe timeout from 5s to 15s. The waitanyinvoice probe normally returns in ~1s but can intermittently take ~8s while lightningd is briefly busy; the 5s cap turned those transient spikes into health-check failures (and, at 3 consecutive, an unnecessary process exit / container restart). 15s absorbs the busy spikes while a genuinely wedged RPC still fails the check. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01DKkev76U4YRnRAqM6jqbae
* ln: bound receive-listener wait, phase-aware watchdog, re-enable health checkAdam Soltys2026-08-221-1/+1
| | | | | | | | | | | | | | | | Give waitanyinvoice an explicit 30s server-side timeout so a dead/half-open socket can no longer hold the listener indefinitely; CLN's 904 timeout during a quiet period is treated as a clean re-arm without counting as a failure. Split the listener into waiting vs processing phases so the watchdog never resets a healthy socket merely because a ledger write is slow, and never starts a second concurrent processor — a stalled processing phase is surfaced loudly instead. Process the settlement and confirm the durable payment pointer BEFORE advancing pay_index, so a store load/restart between the cursor write and credit() cannot drop a received payment. Expose listener status and add a backlog probe to the health check, and re-enable startHealthCheck(). Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01XiwgmQKwKnRxUmVDd4xSf7
* upload: require auth on /upload/:type; bump sharp past libvips CVEs (S7)Adam Soltys2026-08-071-1/+1
| | | | | | | | | | POST /upload/:type fed the raw uploaded image straight into sharp with no auth preValidation (unlike neighboring routes), reaching a native libvips decoder in the container that holds the JWT secret and CLN hot wallet. Require auth, and bump sharp 0.33.5 -> 0.35.3 (out of the vulnerable < 0.35.0 libvips range, GHSA-f88m-g3jw-g9cj et al.). Co-Authored-By: Claude Opus 4.8 <[email protected]>
* bolt12 zaps: pay offers, NWC pay/receive, per-user offers, NIP-44Adam Soltys2026-07-301-0/+1
| | | | | | | | | | | | | | | | - sendLightning fetches an invoice from lno1 offers (payer_note passthrough for NIP-177 zap intents) and pays it through the existing bolt12 path - NWC: new nwc#2 pay/receive methods (BIP-321 URIs, payer proofs stubbed until CLN 26.06 createproof), nip44_v2 alongside nip04 with per-request scheme detection, dual 23196/23197 notifications, 13194 refreshed when its content or encryption tag goes stale - standing per-user bolt12 offer via GET /offer; incoming bolt12 payments record invreq_payer_note as memo - parse/fetchinvoice routes handle offers; zap display parses kind 9736 receipts (amount tag + embedded intent) and drops a call to a sync() helper that never existed Co-Authored-By: Claude Fable 5 <[email protected]>
* Merge remote-tracking branch 'origin/master'Adam Soltys2026-07-111-0/+5
|\ | | | | | | | | # Conflicts: # lib/payments.ts
| * invoices: sell merchant-supplied preimages via a usePreimage queueAdam Soltys2026-07-101-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Merchants POST /preimages (auth) to pre-load 32-byte hex preimages into a FIFO queue; creating an invoice with usePreimage: true consumes the next one so the invoice's payment hash is sha256(preimage). Paying the invoice reveals the merchant-chosen secret to the buyer — via their own wallet on external settlements, and via GET /invoice/:id once settled — enabling backend-less digital download stores (encrypted files on static hosting, preimage + public string = decryption key). - GET /preimages lists the queue with payment hashes so the merchant can map files to future invoices; POST /preimages/delete clears it - empty queue fails invoice creation rather than issuing a random preimage the buyer would pay for but couldn't decrypt with - preimages cln rejects as already used are discarded and the next tried - consumed preimages persist at preimage:${payment_hash} (TTL = invoice expiry) and credit() prefers them as the settlement ref, so internal coinos-to-coinos payments reveal the real preimage instead of the sender's uid Co-Authored-By: Claude Fable 5 <[email protected]>
* | invoices: rate-limit invoice create and update per IPAdam Soltys2026-07-101-2/+2
|/ | | | | | | | Add a per-IP rate limit (30/10s) to POST /invoice and POST /invoice/:id, matching the existing GET /invoice/:id limit, to throttle automated invoice-creation floods. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* users: add authenticated self-delete endpointAdam Soltys2026-06-131-0/+1
| | | | | | | | | | POST /delete (auth) wipes every key tied to the calling user, mirroring scripts/delall-legacy.ts: user records, payments/invoices, sub-accounts, NWC apps, nostr follow graph + nip5. Gated by typing the username and refuses while balance+pending > 10k sats so funds can't be destroyed by accident. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* payments: guard /replay double-credit race with SET NX idempotencyAdam Soltys2026-06-131-1/+1
| | | | | | | | | | getPayment() pre-check in the lightning listener/replay isn't atomic, so concurrent re-credits of the same settlement each ran incrBy. Claim each lightning/bolt12 settlement with an atomic SET NX on credited:<ref> (ref = preimage) and bail if already claimed. Also disable the /replay route that triggered it. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* remove /gateway endpointAdam Soltys2026-05-171-1/+0
| | | | | | | | | Unauthenticated arbitrary db.set abuse vector. Exploited to inflate user balances and override safety controls (bitcoin:limit, limit, hardfreeze, freeze) in real time, leading to a hot-wallet drain. Route and handler both fully removed. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
* check listpays before reversingAdam Soltys2026-04-251-2/+2
|
* lnurl proxyAdam Soltys2026-03-271-0/+1
|
* ensure lightning payments get processedAdam Soltys2026-03-191-1/+2
|
* remove logsAdam Soltys2026-03-171-4/+2
|
* adjust ln minfeeregtest-dataAdam Soltys2026-03-151-1/+1
|
* health checkAdam Soltys2026-02-061-0/+3
|
* challenge verifyAdam Soltys2025-10-011-1/+0
|
* login challengeAdam Soltys2025-10-011-0/+1
|
* Merge branch 'patch-1'Adam Soltys2025-09-181-1/+1
|\
| * allow invoice owners to modify the webhookAdam Soltys2025-09-181-1/+1
| |
* | sendinvoice supportAdam Soltys2025-09-181-0/+1
|/
* flash routeAdam Soltys2025-09-111-2/+2
|
* remove test routeAdam Soltys2025-09-091-1/+0
|
* create external paymentsquareAdam Soltys2025-09-041-0/+1
|
* support readonly tokensAdam Soltys2025-09-041-0/+1
|
* invoice updateAdam Soltys2025-08-201-0/+1
|
* authorizationsAdam Soltys2025-08-101-1/+2
|
* respect null tipsAdam Soltys2025-07-191-0/+1
|
* delete managerAdam Soltys2025-07-181-0/+1
|
* square endpointsAdam Soltys2025-07-171-2/+4
|
* check account ownershipAdam Soltys2025-07-121-0/+3
|
* auto payAdam Soltys2025-07-081-0/+4
|
* lnurl pay endpoint for latest invoiceAdam Soltys2025-05-061-0/+1
|
* creditsAdam Soltys2025-04-071-0/+1
|
* fund routesAdam Soltys2025-03-151-2/+4
|
* nwc date comparison in secondsAdam Soltys2025-03-071-3/+1
|
* record payment_hashAdam Soltys2025-03-051-0/+3
|
* pinned contactsAdam Soltys2025-02-261-0/+3
|
* default app on registerAdam Soltys2025-02-111-1/+1
|
* nwc apps endpointsAdam Soltys2025-02-071-2/+9
|
* log login failuresAdam Soltys2025-02-041-1/+10
|
* unified event endpointAdam Soltys2025-01-231-0/+1
|
* notes and stuffAdam Soltys2025-01-211-0/+1
|
* rm firehoseAdam Soltys2025-01-201-1/+0
|
* nostr threadsAdam Soltys2025-01-201-0/+2
|
* return event partsAdam Soltys2025-01-171-0/+1
|
* zap endpointsAdam Soltys2025-01-161-0/+3
|
* sign endpointAdam Soltys2025-01-151-0/+1
|