From 8bd2f95f25ca00e6bd1cb1a3163b1b4627e7d0a0 Mon Sep 17 00:00:00 2001 From: soufiane Date: Thu, 27 Nov 2025 12:54:22 +0100 Subject: [PATCH] fix: resolve SonarQube security vulnerabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix ReDoS vulnerability in email regex with length limit and safer pattern - Replace Math.random() with crypto.getRandomValues() for secure ID generation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- utils/helpers.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/utils/helpers.ts b/utils/helpers.ts index 73cb261..65b342d 100644 --- a/utils/helpers.ts +++ b/utils/helpers.ts @@ -133,7 +133,10 @@ export const capitalize = (str: string): string => { // Validation Helpers export const isValidEmail = (email: string): boolean => { - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + // Limit input length to prevent ReDoS attacks + if (!email || email.length > 254) return false; + // Simple and safe email regex (non-backtracking) + const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; return emailRegex.test(email); }; @@ -157,9 +160,15 @@ export const deepClone = (obj: T): T => { return JSON.parse(JSON.stringify(obj)); }; -// Generate Random ID +// Generate Random ID (cryptographically secure) export const generateId = (): string => { - return Math.random().toString(36).substring(2) + Date.now().toString(36); + if (typeof window !== 'undefined' && window.crypto) { + const array = new Uint32Array(2); + window.crypto.getRandomValues(array); + return array[0].toString(36) + array[1].toString(36) + Date.now().toString(36); + } + // Fallback for SSR (non-sensitive context) + return Date.now().toString(36) + Math.random().toString(36).substring(2); }; // Debounce Function