Merge pull request #106 from Hexastack/105-issue-insecure-randomness

fix: Insecure randomness
This commit is contained in:
Mohamed Marrouchi 2024-09-30 11:22:59 +01:00 committed by GitHub
commit d9b8c9b4d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 40 additions and 4 deletions

View File

@ -21,6 +21,7 @@ import { PluginType } from '@/plugins/types';
import { Settings } from '@/setting/schemas/types'; import { Settings } from '@/setting/schemas/types';
import { SettingService } from '@/setting/services/setting.service'; import { SettingService } from '@/setting/services/setting.service';
import { BaseService } from '@/utils/generics/base-service'; import { BaseService } from '@/utils/generics/base-service';
import { getRandom } from '@/utils/helpers/safeRandom';
import { BlockRepository } from '../repositories/block.repository'; import { BlockRepository } from '../repositories/block.repository';
import { Block, BlockFull, BlockPopulate } from '../schemas/block.schema'; import { Block, BlockFull, BlockPopulate } from '../schemas/block.schema';
@ -394,7 +395,7 @@ export class BlockService extends BaseService<Block, BlockPopulate, BlockFull> {
*/ */
getRandom<T>(array: T[]): T { getRandom<T>(array: T[]): T {
return Array.isArray(array) return Array.isArray(array)
? array[Math.floor(Math.random() * array.length)] ? array[Math.floor(getRandom() * array.length)]
: array; : array;
} }

View File

@ -27,6 +27,7 @@ import { LanguageModel } from '@/i18n/schemas/language.schema';
import { I18nService } from '@/i18n/services/i18n.service'; import { I18nService } from '@/i18n/services/i18n.service';
import { LanguageService } from '@/i18n/services/language.service'; import { LanguageService } from '@/i18n/services/language.service';
import { LoggerService } from '@/logger/logger.service'; import { LoggerService } from '@/logger/logger.service';
import { getRandom } from '@/utils/helpers/safeRandom';
import { installUserFixtures } from '@/utils/test/fixtures/user'; import { installUserFixtures } from '@/utils/test/fixtures/user';
import { import {
closeInMongodConnection, closeInMongodConnection,
@ -126,7 +127,7 @@ describe('AuthController', () => {
role = await roleService.findOne({}); role = await roleService.findOne({});
baseUser = { baseUser = {
email: 'test@testing.com', email: 'test@testing.com',
password: Math.random().toString(), password: getRandom().toString(),
username: 'test', username: 'test',
first_name: 'test', first_name: 'test',
last_name: 'test', last_name: 'test',

View File

@ -0,0 +1,16 @@
/*
* 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).
*/
import crypto from 'crypto';
/**
* Return a cryptographically secure random value between 0 and 1
*
* @returns A cryptographically secure random value between 0 and 1
*/
export const getRandom = (): number =>
crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32;

View File

@ -26,6 +26,7 @@ import { getAvatarSrc } from "@/components/inbox/helpers/mapMessages";
import { useAuth } from "@/hooks/useAuth"; import { useAuth } from "@/hooks/useAuth";
import { useConfig } from "@/hooks/useConfig"; import { useConfig } from "@/hooks/useConfig";
import { EntityType } from "@/services/types"; import { EntityType } from "@/services/types";
import { getRandom } from "@/utils/safeRandom";
import { borderLine, theme } from "./themes/theme"; import { borderLine, theme } from "./themes/theme";
@ -84,7 +85,7 @@ export const Header: FC<HeaderProps> = ({ isSideBarOpen, onToggleSidebar }) => {
const [randomSeed, setRandomSeed] = useState<string>("randomseed"); const [randomSeed, setRandomSeed] = useState<string>("randomseed");
useEffect(() => { useEffect(() => {
setRandomSeed(Math.random().toString()); setRandomSeed(getRandom().toString());
}, [user]); }, [user]);
return ( return (

View File

@ -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). * 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 { getRandom } from "./safeRandom";
export const generateId = () => { export const generateId = () => {
const d = const d =
typeof performance === "undefined" ? Date.now() : performance.now() * 1000; typeof performance === "undefined" ? Date.now() : performance.now() * 1000;
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
const r = (Math.random() * 16 + d) % 16 | 0; const r = (getRandom() * 16 + d) % 16 | 0;
return (c == "x" ? r : (r & 0x3) | 0x8).toString(16); return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
}); });

View File

@ -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
*
* @returns A cryptographically secure random value between 0 and 1
*/
export const getRandom = (): number =>
window.crypto.getRandomValues(new Uint32Array(1))[0] * Math.pow(2, -32);