mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix: use crypto.getRandomValues() for password generation
Math.random() is not cryptographically secure. Replace with crypto.getRandomValues() in both generatePassword() functions to resolve CodeQL js/insecure-randomness alerts.
This commit is contained in:
@@ -751,20 +751,26 @@ function SecuritySection() {
|
||||
|
||||
/* ────────────────────── People ────────────────────── */
|
||||
|
||||
function secureRandom(max: number): number {
|
||||
const array = new Uint32Array(1);
|
||||
crypto.getRandomValues(array);
|
||||
return array[0] % max;
|
||||
}
|
||||
|
||||
function generatePassword(): string {
|
||||
const upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const lower = "abcdefghijklmnopqrstuvwxyz";
|
||||
const digits = "0123456789";
|
||||
const all = upper + lower + digits;
|
||||
const required = [
|
||||
upper[Math.floor(Math.random() * upper.length)],
|
||||
lower[Math.floor(Math.random() * lower.length)],
|
||||
digits[Math.floor(Math.random() * digits.length)],
|
||||
upper[secureRandom(upper.length)],
|
||||
lower[secureRandom(lower.length)],
|
||||
digits[secureRandom(digits.length)],
|
||||
];
|
||||
const rest = Array.from({ length: 13 }, () => all[Math.floor(Math.random() * all.length)]);
|
||||
const rest = Array.from({ length: 13 }, () => all[secureRandom(all.length)]);
|
||||
const chars = [...required, ...rest];
|
||||
for (let i = chars.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
const j = secureRandom(i + 1);
|
||||
[chars[i], chars[j]] = [chars[j], chars[i]];
|
||||
}
|
||||
return chars.join("");
|
||||
|
||||
@@ -41,22 +41,26 @@ function triggerBrowserPasswordSave(username: string, password: string) {
|
||||
// The form.submit() causes a full page navigation to "/", so no cleanup needed.
|
||||
}
|
||||
|
||||
function secureRandom(max: number): number {
|
||||
const array = new Uint32Array(1);
|
||||
crypto.getRandomValues(array);
|
||||
return array[0] % max;
|
||||
}
|
||||
|
||||
function generatePassword(): string {
|
||||
const upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const lower = "abcdefghijklmnopqrstuvwxyz";
|
||||
const digits = "0123456789";
|
||||
const all = upper + lower + digits;
|
||||
// Guarantee at least one of each required character class
|
||||
const required = [
|
||||
upper[Math.floor(Math.random() * upper.length)],
|
||||
lower[Math.floor(Math.random() * lower.length)],
|
||||
digits[Math.floor(Math.random() * digits.length)],
|
||||
upper[secureRandom(upper.length)],
|
||||
lower[secureRandom(lower.length)],
|
||||
digits[secureRandom(digits.length)],
|
||||
];
|
||||
const rest = Array.from({ length: 13 }, () => all[Math.floor(Math.random() * all.length)]);
|
||||
// Shuffle so the required chars aren't always at the start
|
||||
const rest = Array.from({ length: 13 }, () => all[secureRandom(all.length)]);
|
||||
const chars = [...required, ...rest];
|
||||
for (let i = chars.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
const j = secureRandom(i + 1);
|
||||
[chars[i], chars[j]] = [chars[j], chars[i]];
|
||||
}
|
||||
return chars.join("");
|
||||
|
||||
Reference in New Issue
Block a user