From 3887f414ee0293d99e84b8dcc2d858d25e7bb724 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 13 Feb 2026 20:42:08 +0530 Subject: [PATCH] fix: add input validation for account creation - Validate connector type against known connectors - Check that config is a non-empty string - Check that name is a non-empty string - Return clear error messages for each validation failure - Add unit tests for all validation cases - Resolves TODO comments for missing validations --- .../actions/accounts/__tests__/add.test.ts | 71 +++++++++++++++++++ .../background-script/actions/accounts/add.ts | 27 ++++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/extension/background-script/actions/accounts/__tests__/add.test.ts b/src/extension/background-script/actions/accounts/__tests__/add.test.ts index 1948d04cbb..e7f77acace 100644 --- a/src/extension/background-script/actions/accounts/__tests__/add.test.ts +++ b/src/extension/background-script/actions/accounts/__tests__/add.test.ts @@ -4,6 +4,26 @@ import type { MessageAccountAdd } from "~/types"; import addAccount from "../add"; jest.mock("~/extension/background-script/state"); +jest.mock("~/extension/background-script/connectors", () => ({ + __esModule: true, + default: { + lnd: {}, + nativelnd: {}, + lndhub: {}, + nativelndhub: {}, + kollider: {}, + lnbits: {}, + lnc: {}, + nativelnbits: {}, + galoy: {}, + eclair: {}, + citadel: {}, + nativecitadel: {}, + alby: {}, + nwc: {}, + lawallet: {}, + }, +})); jest.mock("uuid", () => { return { v4: jest.fn(() => "random-id-42"), @@ -128,4 +148,55 @@ describe("add account to account-list", () => { expect(spy).toHaveBeenCalledTimes(1); }); + + test("returns error for invalid connector type", async () => { + const mockState = defaultMockState; + state.getState = jest.fn().mockReturnValue(mockState); + + const invalidMessage: MessageAccountAdd = { + ...message, + args: { + ...message.args, + connector: "fakeconnector" as never, + }, + }; + + expect(await addAccount(invalidMessage)).toStrictEqual({ + error: "Invalid connector type", + }); + }); + + test("returns error for missing config", async () => { + const mockState = defaultMockState; + state.getState = jest.fn().mockReturnValue(mockState); + + const invalidMessage: MessageAccountAdd = { + ...message, + args: { + ...message.args, + config: "", + }, + }; + + expect(await addAccount(invalidMessage)).toStrictEqual({ + error: "Account config is required", + }); + }); + + test("returns error for missing name", async () => { + const mockState = defaultMockState; + state.getState = jest.fn().mockReturnValue(mockState); + + const invalidMessage: MessageAccountAdd = { + ...message, + args: { + ...message.args, + name: "", + }, + }; + + expect(await addAccount(invalidMessage)).toStrictEqual({ + error: "Account name is required", + }); + }); }); diff --git a/src/extension/background-script/actions/accounts/add.ts b/src/extension/background-script/actions/accounts/add.ts index 04fe49d0dd..d6cc4b020b 100644 --- a/src/extension/background-script/actions/accounts/add.ts +++ b/src/extension/background-script/actions/accounts/add.ts @@ -1,17 +1,40 @@ import { v4 as uuidv4 } from "uuid"; import { encryptData } from "~/common/lib/crypto"; import { getUniqueAccountName } from "~/common/utils/validations"; +import connectors from "~/extension/background-script/connectors"; import state from "~/extension/background-script/state"; import type { MessageAccountAdd } from "~/types"; const add = async (message: MessageAccountAdd) => { const newAccount = message.args; + + // Validate connector type + if (!newAccount.connector || !(newAccount.connector in connectors)) { + return { error: "Invalid connector type" }; + } + + // Validate config is present + if ( + !newAccount.config || + typeof newAccount.config !== "string" || + newAccount.config.trim() === "" + ) { + return { error: "Account config is required" }; + } + + // Validate name is present + if ( + !newAccount.name || + typeof newAccount.name !== "string" || + newAccount.name.trim() === "" + ) { + return { error: "Account name is required" }; + } + const accounts = state.getState().accounts; const name = getUniqueAccountName(newAccount.name, accounts); const tmpAccounts = { ...accounts }; - // TODO: add validations - // TODO: make sure a password is set const password = await state.getState().password(); if (!password) return { error: "Password is missing" };