Skip to content

Commit

Permalink
Merge pull request #106 from Hexastack/105-issue-insecure-randomness
Browse files Browse the repository at this point in the history
fix: Insecure randomness
  • Loading branch information
marrouchi authored Sep 30, 2024
2 parents 04ce4f2 + f0a0733 commit d9b8c9b
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 4 deletions.
3 changes: 2 additions & 1 deletion api/src/chat/services/block.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 { getRandom } from '@/utils/helpers/safeRandom';

import { BlockRepository } from '../repositories/block.repository';
import { Block, BlockFull, BlockPopulate } from '../schemas/block.schema';
Expand Down Expand Up @@ -394,7 +395,7 @@ export class BlockService extends BaseService<Block, BlockPopulate, BlockFull> {
*/
getRandom<T>(array: T[]): T {
return Array.isArray(array)
? array[Math.floor(Math.random() * array.length)]
? array[Math.floor(getRandom() * array.length)]
: array;
}

Expand Down
3 changes: 2 additions & 1 deletion api/src/user/controllers/auth.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 { getRandom } from '@/utils/helpers/safeRandom';
import { installUserFixtures } from '@/utils/test/fixtures/user';
import {
closeInMongodConnection,
Expand Down Expand Up @@ -126,7 +127,7 @@ describe('AuthController', () => {
role = await roleService.findOne({});
baseUser = {
email: '[email protected]',
password: Math.random().toString(),
password: getRandom().toString(),
username: 'test',
first_name: 'test',
last_name: 'test',
Expand Down
16 changes: 16 additions & 0 deletions api/src/utils/helpers/safeRandom.ts
Original file line number Diff line number Diff line change
@@ -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;
3 changes: 2 additions & 1 deletion frontend/src/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 { getRandom } from "@/utils/safeRandom";

import { borderLine, theme } from "./themes/theme";

Expand Down Expand Up @@ -84,7 +85,7 @@ export const Header: FC<HeaderProps> = ({ isSideBarOpen, onToggleSidebar }) => {
const [randomSeed, setRandomSeed] = useState<string>("randomseed");

useEffect(() => {
setRandomSeed(Math.random().toString());
setRandomSeed(getRandom().toString());
}, [user]);

return (
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/utils/generateId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 { 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 = (Math.random() * 16 + d) % 16 | 0;
const r = (getRandom() * 16 + d) % 16 | 0;

return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
});
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/utils/safeRandom.ts
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit d9b8c9b

Please sign in to comment.