From 00fa4316be6ad85a8a31469f4c0f57ded7dd8c4d Mon Sep 17 00:00:00 2001 From: yassinedorbozgithub Date: Mon, 30 Sep 2024 06:32:43 +0100 Subject: [PATCH 1/5] fix(api): Insecure randomness --- api/src/chat/services/block.service.ts | 3 ++- api/src/user/controllers/auth.controller.spec.ts | 3 ++- api/src/utils/helpers/safeRandom.ts | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 api/src/utils/helpers/safeRandom.ts diff --git a/api/src/chat/services/block.service.ts b/api/src/chat/services/block.service.ts index 1b07a47..2944070 100644 --- a/api/src/chat/services/block.service.ts +++ b/api/src/chat/services/block.service.ts @@ -21,6 +21,7 @@ import { PluginType } from '@/plugins/types'; import { Settings } from '@/setting/schemas/types'; import { SettingService } from '@/setting/services/setting.service'; import { BaseService } from '@/utils/generics/base-service'; +import { getRadom } from '@/utils/helpers/safeRandom'; import { BlockRepository } from '../repositories/block.repository'; import { Block, BlockFull, BlockPopulate } from '../schemas/block.schema'; @@ -394,7 +395,7 @@ export class BlockService extends BaseService { */ getRandom(array: T[]): T { return Array.isArray(array) - ? array[Math.floor(Math.random() * array.length)] + ? array[Math.floor(getRadom() * array.length)] : array; } diff --git a/api/src/user/controllers/auth.controller.spec.ts b/api/src/user/controllers/auth.controller.spec.ts index 5f49350..3d8932d 100644 --- a/api/src/user/controllers/auth.controller.spec.ts +++ b/api/src/user/controllers/auth.controller.spec.ts @@ -27,6 +27,7 @@ import { LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; import { LoggerService } from '@/logger/logger.service'; +import { getRadom } from '@/utils/helpers/safeRandom'; import { installUserFixtures } from '@/utils/test/fixtures/user'; import { closeInMongodConnection, @@ -126,7 +127,7 @@ describe('AuthController', () => { role = await roleService.findOne({}); baseUser = { email: 'test@testing.com', - password: Math.random().toString(), + password: getRadom().toString(), username: 'test', first_name: 'test', last_name: 'test', diff --git a/api/src/utils/helpers/safeRandom.ts b/api/src/utils/helpers/safeRandom.ts new file mode 100644 index 0000000..539677b --- /dev/null +++ b/api/src/utils/helpers/safeRandom.ts @@ -0,0 +1,15 @@ +/* + * Copyright © 2024 Hexastack. All rights reserved. + * + * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: + * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. + * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). + */ + +/** + * Return a cryptographically secure random value between 0 and 1 is desired + * + * @returns A cryptographically secure random value between 0 and 1 is desired + */ +export const getRadom = (): number => + window.crypto.getRandomValues(new Uint32Array(1))[0] * Math.pow(2, -32); From 1183473aaf6ebdc78dc8b8a4087e6a3dc8437dca Mon Sep 17 00:00:00 2001 From: yassinedorbozgithub Date: Mon, 30 Sep 2024 06:33:00 +0100 Subject: [PATCH 2/5] fix(frontend): Insecure randomness --- frontend/src/layout/Header.tsx | 3 ++- frontend/src/utils/generateId.ts | 4 +++- frontend/src/utils/safeRandom.ts | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 frontend/src/utils/safeRandom.ts diff --git a/frontend/src/layout/Header.tsx b/frontend/src/layout/Header.tsx index 49a912a..81ed200 100644 --- a/frontend/src/layout/Header.tsx +++ b/frontend/src/layout/Header.tsx @@ -26,6 +26,7 @@ import { getAvatarSrc } from "@/components/inbox/helpers/mapMessages"; import { useAuth } from "@/hooks/useAuth"; import { useConfig } from "@/hooks/useConfig"; import { EntityType } from "@/services/types"; +import { getRadom } from "@/utils/safeRandom"; import { borderLine, theme } from "./themes/theme"; @@ -84,7 +85,7 @@ export const Header: FC = ({ isSideBarOpen, onToggleSidebar }) => { const [randomSeed, setRandomSeed] = useState("randomseed"); useEffect(() => { - setRandomSeed(Math.random().toString()); + setRandomSeed(getRadom().toString()); }, [user]); return ( diff --git a/frontend/src/utils/generateId.ts b/frontend/src/utils/generateId.ts index fb857e9..2dbac09 100644 --- a/frontend/src/utils/generateId.ts +++ b/frontend/src/utils/generateId.ts @@ -6,12 +6,14 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ +import { getRadom } from "./safeRandom"; + export const generateId = () => { const d = typeof performance === "undefined" ? Date.now() : performance.now() * 1000; return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { - const r = (Math.random() * 16 + d) % 16 | 0; + const r = (getRadom() * 16 + d) % 16 | 0; return (c == "x" ? r : (r & 0x3) | 0x8).toString(16); }); diff --git a/frontend/src/utils/safeRandom.ts b/frontend/src/utils/safeRandom.ts new file mode 100644 index 0000000..539677b --- /dev/null +++ b/frontend/src/utils/safeRandom.ts @@ -0,0 +1,15 @@ +/* + * Copyright © 2024 Hexastack. All rights reserved. + * + * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: + * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. + * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). + */ + +/** + * Return a cryptographically secure random value between 0 and 1 is desired + * + * @returns A cryptographically secure random value between 0 and 1 is desired + */ +export const getRadom = (): number => + window.crypto.getRandomValues(new Uint32Array(1))[0] * Math.pow(2, -32); From 8383dc3c3ed7a8666541e26db72bfb8289e089e9 Mon Sep 17 00:00:00 2001 From: yassinedorbozgithub Date: Mon, 30 Sep 2024 06:36:50 +0100 Subject: [PATCH 3/5] fix: function jsdoc description --- api/src/utils/helpers/safeRandom.ts | 4 ++-- frontend/src/utils/safeRandom.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/src/utils/helpers/safeRandom.ts b/api/src/utils/helpers/safeRandom.ts index 539677b..a7aa789 100644 --- a/api/src/utils/helpers/safeRandom.ts +++ b/api/src/utils/helpers/safeRandom.ts @@ -7,9 +7,9 @@ */ /** - * Return a cryptographically secure random value between 0 and 1 is desired + * Return a cryptographically secure random value between 0 and 1 * - * @returns A cryptographically secure random value between 0 and 1 is desired + * @returns A cryptographically secure random value between 0 and 1 */ export const getRadom = (): number => window.crypto.getRandomValues(new Uint32Array(1))[0] * Math.pow(2, -32); diff --git a/frontend/src/utils/safeRandom.ts b/frontend/src/utils/safeRandom.ts index 539677b..a7aa789 100644 --- a/frontend/src/utils/safeRandom.ts +++ b/frontend/src/utils/safeRandom.ts @@ -7,9 +7,9 @@ */ /** - * Return a cryptographically secure random value between 0 and 1 is desired + * Return a cryptographically secure random value between 0 and 1 * - * @returns A cryptographically secure random value between 0 and 1 is desired + * @returns A cryptographically secure random value between 0 and 1 */ export const getRadom = (): number => window.crypto.getRandomValues(new Uint32Array(1))[0] * Math.pow(2, -32); From cefbe16b84409ef5ace98db843235510857245cd Mon Sep 17 00:00:00 2001 From: yassinedorbozgithub Date: Mon, 30 Sep 2024 09:26:41 +0100 Subject: [PATCH 4/5] fix: window is not defined --- api/src/utils/helpers/safeRandom.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/src/utils/helpers/safeRandom.ts b/api/src/utils/helpers/safeRandom.ts index a7aa789..d3c2382 100644 --- a/api/src/utils/helpers/safeRandom.ts +++ b/api/src/utils/helpers/safeRandom.ts @@ -5,6 +5,7 @@ * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ +import crypto from 'crypto'; /** * Return a cryptographically secure random value between 0 and 1 @@ -12,4 +13,4 @@ * @returns A cryptographically secure random value between 0 and 1 */ export const getRadom = (): number => - window.crypto.getRandomValues(new Uint32Array(1))[0] * Math.pow(2, -32); + crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32; From f0a0733eb4a89ee6e70ad54bc4ff6acafef9d876 Mon Sep 17 00:00:00 2001 From: yassinedorbozgithub Date: Mon, 30 Sep 2024 11:13:47 +0100 Subject: [PATCH 5/5] fix: feedback udaptes --- api/src/chat/services/block.service.ts | 4 ++-- api/src/user/controllers/auth.controller.spec.ts | 4 ++-- api/src/utils/helpers/safeRandom.ts | 2 +- frontend/src/layout/Header.tsx | 4 ++-- frontend/src/utils/generateId.ts | 4 ++-- frontend/src/utils/safeRandom.ts | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/api/src/chat/services/block.service.ts b/api/src/chat/services/block.service.ts index 2944070..f1b02c9 100644 --- a/api/src/chat/services/block.service.ts +++ b/api/src/chat/services/block.service.ts @@ -21,7 +21,7 @@ import { PluginType } from '@/plugins/types'; import { Settings } from '@/setting/schemas/types'; import { SettingService } from '@/setting/services/setting.service'; import { BaseService } from '@/utils/generics/base-service'; -import { getRadom } from '@/utils/helpers/safeRandom'; +import { getRandom } from '@/utils/helpers/safeRandom'; import { BlockRepository } from '../repositories/block.repository'; import { Block, BlockFull, BlockPopulate } from '../schemas/block.schema'; @@ -395,7 +395,7 @@ export class BlockService extends BaseService { */ getRandom(array: T[]): T { return Array.isArray(array) - ? array[Math.floor(getRadom() * array.length)] + ? array[Math.floor(getRandom() * array.length)] : array; } diff --git a/api/src/user/controllers/auth.controller.spec.ts b/api/src/user/controllers/auth.controller.spec.ts index 3d8932d..bc85e2c 100644 --- a/api/src/user/controllers/auth.controller.spec.ts +++ b/api/src/user/controllers/auth.controller.spec.ts @@ -27,7 +27,7 @@ import { LanguageModel } from '@/i18n/schemas/language.schema'; import { I18nService } from '@/i18n/services/i18n.service'; import { LanguageService } from '@/i18n/services/language.service'; import { LoggerService } from '@/logger/logger.service'; -import { getRadom } from '@/utils/helpers/safeRandom'; +import { getRandom } from '@/utils/helpers/safeRandom'; import { installUserFixtures } from '@/utils/test/fixtures/user'; import { closeInMongodConnection, @@ -127,7 +127,7 @@ describe('AuthController', () => { role = await roleService.findOne({}); baseUser = { email: 'test@testing.com', - password: getRadom().toString(), + password: getRandom().toString(), username: 'test', first_name: 'test', last_name: 'test', diff --git a/api/src/utils/helpers/safeRandom.ts b/api/src/utils/helpers/safeRandom.ts index d3c2382..48f0a4a 100644 --- a/api/src/utils/helpers/safeRandom.ts +++ b/api/src/utils/helpers/safeRandom.ts @@ -12,5 +12,5 @@ import crypto from 'crypto'; * * @returns A cryptographically secure random value between 0 and 1 */ -export const getRadom = (): number => +export const getRandom = (): number => crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32; diff --git a/frontend/src/layout/Header.tsx b/frontend/src/layout/Header.tsx index 81ed200..53297a2 100644 --- a/frontend/src/layout/Header.tsx +++ b/frontend/src/layout/Header.tsx @@ -26,7 +26,7 @@ import { getAvatarSrc } from "@/components/inbox/helpers/mapMessages"; import { useAuth } from "@/hooks/useAuth"; import { useConfig } from "@/hooks/useConfig"; import { EntityType } from "@/services/types"; -import { getRadom } from "@/utils/safeRandom"; +import { getRandom } from "@/utils/safeRandom"; import { borderLine, theme } from "./themes/theme"; @@ -85,7 +85,7 @@ export const Header: FC = ({ isSideBarOpen, onToggleSidebar }) => { const [randomSeed, setRandomSeed] = useState("randomseed"); useEffect(() => { - setRandomSeed(getRadom().toString()); + setRandomSeed(getRandom().toString()); }, [user]); return ( diff --git a/frontend/src/utils/generateId.ts b/frontend/src/utils/generateId.ts index 2dbac09..0f498d8 100644 --- a/frontend/src/utils/generateId.ts +++ b/frontend/src/utils/generateId.ts @@ -6,14 +6,14 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { getRadom } from "./safeRandom"; +import { getRandom } from "./safeRandom"; export const generateId = () => { const d = typeof performance === "undefined" ? Date.now() : performance.now() * 1000; return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { - const r = (getRadom() * 16 + d) % 16 | 0; + const r = (getRandom() * 16 + d) % 16 | 0; return (c == "x" ? r : (r & 0x3) | 0x8).toString(16); }); diff --git a/frontend/src/utils/safeRandom.ts b/frontend/src/utils/safeRandom.ts index a7aa789..ac4b9c6 100644 --- a/frontend/src/utils/safeRandom.ts +++ b/frontend/src/utils/safeRandom.ts @@ -11,5 +11,5 @@ * * @returns A cryptographically secure random value between 0 and 1 */ -export const getRadom = (): number => +export const getRandom = (): number => window.crypto.getRandomValues(new Uint32Array(1))[0] * Math.pow(2, -32);