fix(security): P1 money-oracle hardening — fail-closed BCI, amount/account match guard, no 172.* admin #1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/security-audit-p1"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Security P1 fixes — kua-cashier (the payment-confirmation "money truth")
Fixes the P1s (plus low-risk P2/P3 wins) from the read-only audit
(
sec-audit-kua-cashier.md). Every finding was verified against source first.kua-cashier fires real
payment.confirmedcallbacks that release downstream goods,so each of these was a direct free-goods / underpayment vector.
Reviewed (self-reviewed diff), NOT deployed. No service run, no prod touched.
Fixes → findings
server.js/bci/notify503whenBCI_WEBHOOK_SECRETunset; verify secret from a header first (x-webhook-token/apikey/x-apikey),?token=kept only as BCI URL-callback fallback and redacted from logs;timingSafeEqualcompare.matcher.jstier 1inbound.amount >= exact_amountAND matchingaccount_idon the reference path; otherwise fall through.172.*/ loopback source IP auto-grantedtag:admin, no credsserver.jsauth hooktrustProxy: falsesoreq.ipcan't be spoofed via forwarded headers.NODE_ENV != productionserver.jsauth hook!DEVgate.server.jsloggerreqserializer.server.js+migrations/003_admin_audit.sqladmin_audittable records actor (bearer / Tailscale identity), action, target for intent create/cancel, account upsert, inbound inject, manual match/expire.util.jstimingSafeStrEqPreserved (verified intact)
dispatcher.js) — untouched.global66.js) — untouched; adopted the same pattern for BCI.Tests / checks
node --checkpasses on all changed files.test/matcher.test.mjs(4 tests, DI'd query): valid code + full amount + same account → match; 1-peso underpay → NO match; different account → NO match; overpay → match. All pass.test/global66.test.mjs(6 tests) still passes (GLOBAL66_API_KEY=testkey).Deploy notes (for the human merger)
migrations/003_admin_audit.sqlis additive (CREATE TABLE IF NOT EXISTS), applied on next start by the existingmigrate()./bci/notifynow fails closed: confirmBCI_WEBHOOK_SECRETis set in kua-vaultkua-cashier/prodbefore rollout, or BCI callbacks will503.?token=fallback keeps the live BCI URL-callback flow working, so no BCI re-subscription is required.🤖 Generated with Claude Code
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.