Skip to content

Commit ff4d2b2

Browse files
committed
fix: replace Math.random ID generator with crypto-based genId to resolve security hotspot warnings
1 parent f9406f3 commit ff4d2b2

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

src/api/events.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ const wait = (ms = 300) => new Promise(r => setTimeout(r, ms));
99
const NS = 'hgn_event_mock_v1:'; // storage namespace version
1010

1111
const todayISO = () => new Date().toISOString();
12-
const randomPick = arr => arr[Math.floor(Math.random() * arr.length)];
1312
const clone = x => JSON.parse(JSON.stringify(x));
1413

1514
function keyFor(id) {
@@ -205,7 +204,13 @@ export async function upsertScheduleSlot(activityId, date, slot /* {id?,start,en
205204
const next = clone(evt);
206205
const list = next.scheduleByDate[date] ?? [];
207206
if (!slot.id) {
208-
slot.id = crypto.randomUUID ? crypto.randomUUID() : `slot_${Date.now()}`;
207+
slot.id = crypto?.randomUUID
208+
? crypto.randomUUID()
209+
: (() => {
210+
const a = new Uint32Array(4);
211+
crypto?.getRandomValues?.(a);
212+
return `slot_${[...a].map(x => x.toString(16).padStart(8, '0')).join('')}`;
213+
})();
209214
list.push(slot);
210215
} else {
211216
const idx = list.findIndex(s => s.id === slot.id);
@@ -278,7 +283,13 @@ export async function upsertResource(activityId, res /* {id?,type,title,url,size
278283
const next = clone(evt);
279284
const list = next.resources ?? [];
280285
if (!res.id) {
281-
res.id = crypto.randomUUID ? crypto.randomUUID() : `res_${Date.now()}`;
286+
res.id = crypto?.randomUUID
287+
? crypto.randomUUID()
288+
: (() => {
289+
const a = new Uint32Array(4);
290+
crypto?.getRandomValues?.(a);
291+
return `res_${[...a].map(x => x.toString(16).padStart(8, '0')).join('')}`;
292+
})();
282293
list.push(res);
283294
} else {
284295
const idx = list.findIndex(r => r.id === res.id);

src/components/CommunityPortal/Activities/activityId/EventPageOrganizer/sections/DescriptionSection/DescriptionSection.jsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ import { Button } from '../../components/ui/button';
44
import { Textarea } from '../../components/ui/textarea';
55
import styles from './DescriptionSection.module.css';
66

7+
const genId = () => {
8+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
9+
return crypto.randomUUID();
10+
}
11+
12+
if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {
13+
const a = new Uint32Array(4);
14+
crypto.getRandomValues(a);
15+
return [...a].map(x => x.toString(16).padStart(8, '0')).join('');
16+
}
17+
18+
return `id_${Date.now().toString(36)}_${Math.trunc(performance.now()).toString(36)}`;
19+
};
20+
721
export const DescriptionSection = ({
822
activityId = 'test-event',
923
initialDescription = '',
@@ -27,9 +41,7 @@ export const DescriptionSection = ({
2741
try {
2842
const uploads = await Promise.all(files.map(f => uploadMediaFn(activityId, f)));
2943
const newMedia = uploads.map(u => ({
30-
id: Math.random()
31-
.toString(36)
32-
.substr(2, 9),
44+
id: genId(),
3345
url: u.url,
3446
name: u.name,
3547
size: u.size,
@@ -44,9 +56,7 @@ export const DescriptionSection = ({
4456
} else {
4557
// fallback: use local preview URLs
4658
const newMedia = files.map(file => ({
47-
id: Math.random()
48-
.toString(36)
49-
.substr(2, 9),
59+
id: genId(),
5060
url: URL.createObjectURL(file),
5161
name: file.name,
5262
size: file.size,

0 commit comments

Comments
 (0)