aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/auth.ts9
-rw-r--r--lib/payments.ts8
2 files changed, 16 insertions, 1 deletions
diff --git a/lib/auth.ts b/lib/auth.ts
index 30d5438b..c8d5afab 100644
--- a/lib/auth.ts
+++ b/lib/auth.ts
@@ -49,5 +49,12 @@ export const admin = async (c, next) => {
};
export const requirePin = async ({ body, user }) => {
- if (!user || (user.pin && user.pin !== body.pin)) fail("Invalid pin");
+ if (!user) fail("Invalid pin");
+ if (user.pin && (!body?.pin || user.pin !== body.pin)) fail("Invalid pin");
+};
+
+export const requireAccountOwnership = async (db, uid, aid) => {
+ if (!aid || aid === uid) return;
+ const index = await db.lPos(`${uid}:accounts`, aid);
+ if (index === null) fail("unauthorized");
};
diff --git a/lib/payments.ts b/lib/payments.ts
index 2737f886..78f20684 100644
--- a/lib/payments.ts
+++ b/lib/payments.ts
@@ -152,6 +152,12 @@ export const debit = async ({
}) => {
amount = Number.parseInt(amount);
+ // Defense-in-depth: verify account ownership at the debit level
+ if (aid && user && aid !== user.id) {
+ const index = await db.lPos(`${user.id}:accounts`, aid);
+ if (index === null) fail("unauthorized");
+ }
+
const whitelisted = await db.sIsMember("whitelist", user?.username?.toLowerCase().trim());
const blacklisted = await db.sIsMember("blacklist", user?.username?.toLowerCase().trim());
@@ -715,6 +721,8 @@ export const sendOnchain = async (params) => {
// Non-custodial bitcoin account — use esplora
if (aid !== user.id) {
+ const index = await db.lPos(`${user.id}:accounts`, aid);
+ if (index === null) fail("unauthorized");
return sendNonCustodial(params);
}