aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-10-06 15:53:18 -0700
committerAdam Soltys <[email protected]>2026-10-06 15:53:18 -0700
commit7727b97c71c11b4b65f47bcc68460ea981c1b22c (patch)
treeb43f418640cc282ea97c6bf3df56693d34d2866f
parent41018c30a2e03f5ab05be64d419542be0cff7943 (diff)
downloadcoinos-server-7727b97c71c11b4b65f47bcc68460ea981c1b22c.tar.gz
coinos-server-7727b97c71c11b4b65f47bcc68460ea981c1b22c.zip
invoices: a supplied account must belong to the invoice's user
generate() took any existing account id as the credit target, so an invoice could carry one user's name while paying into someone else's account. A supplied aid now has to be in the invoice user's own account list; otherwise the invoice credits that user's main account. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01KCxLg8s1g8yBwjRwPN4uJR
-rw-r--r--lib/invoices.ts7
1 files changed, 6 insertions, 1 deletions
diff --git a/lib/invoices.ts b/lib/invoices.ts
index 7f25f4ba..c4e6a131 100644
--- a/lib/invoices.ts
+++ b/lib/invoices.ts
@@ -57,7 +57,12 @@ export const generate = async ({ invoice, user }) => {
if (!user) fail("user not provided");
if (typeof prompt === "undefined") prompt = user.prompt;
- let account = await g(`account:${aid}`);
+ // The invoice shows `user`'s name but credits `aid`, so a supplied aid must
+ // be one of that user's own accounts — otherwise anyone could put a
+ // merchant's name on an invoice that pays their own account.
+ if (aid && aid !== user.id && (await db.lPos(`${user.id}:accounts`, aid)) === null)
+ aid = undefined;
+ let account = aid ? await g(`account:${aid}`) : null;
if (!account) account = await g(`account:${user.id}`);
if (!account) fail("account not found");
aid = account.id;