Skip to content

Commit 4233ba3

Browse files
committed
Fix cryptographic random bias (CodeQL js/biased-cryptographic-random)
Reimplemented getUnbiasedRandomInRange() using rejection sampling for all range sizes to eliminate modulo bias and ensure uniform cryptographically secure randomness.
1 parent 333c4b8 commit 4233ba3

File tree

3 files changed

+40
-56
lines changed

3 files changed

+40
-56
lines changed

dist/app-boot.js

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8196,36 +8196,29 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
81968196
// Helper function to generate unbiased random values in a range
81978197
getUnbiasedRandomInRange(min, max) {
81988198
const range = max - min + 1;
8199-
if (range > 256) {
8200-
const bytesNeeded = Math.ceil(Math.log2(range) / 8);
8201-
const maxValue = Math.pow(256, bytesNeeded);
8202-
const threshold = maxValue - maxValue % range;
8203-
let randomValue2;
8204-
do {
8205-
const randomBytes = crypto.getRandomValues(new Uint8Array(bytesNeeded));
8206-
randomValue2 = 0;
8207-
for (let i = 0; i < bytesNeeded; i++) {
8208-
randomValue2 = (randomValue2 << 8) + randomBytes[i];
8209-
}
8210-
} while (randomValue2 >= threshold);
8211-
return randomValue2 % range + min;
8212-
}
8199+
if (range <= 0) throw new Error("Invalid range");
8200+
const bytesNeeded = Math.ceil(Math.log2(range) / 8);
8201+
const maxValue = Math.pow(256, bytesNeeded);
8202+
const threshold = maxValue - maxValue % range;
82138203
let randomValue;
82148204
do {
8215-
randomValue = crypto.getRandomValues(new Uint8Array(1))[0];
8216-
} while (randomValue >= 256 - 256 % range);
8205+
const randomBytes = crypto.getRandomValues(new Uint8Array(bytesNeeded));
8206+
randomValue = 0;
8207+
for (let i = 0; i < bytesNeeded; i++) {
8208+
randomValue = randomValue << 8 | randomBytes[i];
8209+
}
8210+
} while (randomValue >= threshold);
82178211
return randomValue % range + min;
82188212
}
82198213
// Generate fingerprint mask for anti-fingerprinting with enhanced randomization
82208214
generateFingerprintMask() {
82218215
const cryptoRandom = crypto.getRandomValues(new Uint8Array(128));
82228216
const mask = {
82238217
timingOffset: this.getUnbiasedRandomInRange(0, 1500),
8224-
// 0-1500ms
8218+
// 01500ms
82258219
sizeVariation: this.getUnbiasedRandomInRange(75, 125) / 100,
8226-
// 0.75 to 1.25
8220+
// 0.751.25
82278221
noisePattern: Array.from(crypto.getRandomValues(new Uint8Array(64))),
8228-
// Increased size
82298222
headerVariations: [
82308223
"X-Client-Version",
82318224
"X-Session-ID",
@@ -8240,11 +8233,9 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
82408233
"X-Private"
82418234
],
82428235
noiseIntensity: this.getUnbiasedRandomInRange(50, 150),
8243-
// 50-150%
8236+
// 50150%
82448237
sizeMultiplier: this.getUnbiasedRandomInRange(75, 125) / 100,
8245-
// 0.75-1.25
82468238
timingVariation: this.getUnbiasedRandomInRange(100, 1100)
8247-
// 100-1100ms
82488239
};
82498240
return mask;
82508241
}

dist/app-boot.js.map

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/network/EnhancedSecureWebRTCManager.js

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4483,54 +4483,47 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
44834483

44844484
// Helper function to generate unbiased random values in a range
44854485
getUnbiasedRandomInRange(min, max) {
4486-
const range = max - min + 1;
4487-
4488-
// If range is larger than 256, use multiple bytes
4489-
if (range > 256) {
4490-
const bytesNeeded = Math.ceil(Math.log2(range) / 8);
4491-
const maxValue = Math.pow(256, bytesNeeded);
4492-
const threshold = maxValue - (maxValue % range);
4493-
4494-
let randomValue;
4495-
do {
4496-
const randomBytes = crypto.getRandomValues(new Uint8Array(bytesNeeded));
4497-
randomValue = 0;
4498-
for (let i = 0; i < bytesNeeded; i++) {
4499-
randomValue = (randomValue << 8) + randomBytes[i];
4500-
}
4501-
} while (randomValue >= threshold);
4502-
4503-
return (randomValue % range) + min;
4504-
}
4505-
4506-
// For ranges <= 256, use single byte with rejection sampling
4486+
const range = max - min + 1;
4487+
if (range <= 0) throw new Error('Invalid range');
4488+
4489+
// Use rejection sampling to avoid modulo bias
4490+
const bytesNeeded = Math.ceil(Math.log2(range) / 8);
4491+
const maxValue = Math.pow(256, bytesNeeded);
4492+
const threshold = maxValue - (maxValue % range);
4493+
45074494
let randomValue;
45084495
do {
4509-
randomValue = crypto.getRandomValues(new Uint8Array(1))[0];
4510-
} while (randomValue >= 256 - (256 % range));
4496+
const randomBytes = crypto.getRandomValues(new Uint8Array(bytesNeeded));
4497+
randomValue = 0;
4498+
for (let i = 0; i < bytesNeeded; i++) {
4499+
randomValue = (randomValue << 8) | randomBytes[i];
4500+
}
4501+
} while (randomValue >= threshold); // discard biased values
4502+
45114503
return (randomValue % range) + min;
45124504
}
4505+
45134506

45144507
// Generate fingerprint mask for anti-fingerprinting with enhanced randomization
45154508
generateFingerprintMask() {
4516-
// Enhanced randomization to prevent side-channel attacks
45174509
const cryptoRandom = crypto.getRandomValues(new Uint8Array(128));
4518-
4510+
45194511
const mask = {
4520-
timingOffset: this.getUnbiasedRandomInRange(0, 1500), // 0-1500ms
4521-
sizeVariation: this.getUnbiasedRandomInRange(75, 125) / 100, // 0.75 to 1.25
4522-
noisePattern: Array.from(crypto.getRandomValues(new Uint8Array(64))), // Increased size
4512+
timingOffset: this.getUnbiasedRandomInRange(0, 1500), // 01500ms
4513+
sizeVariation: this.getUnbiasedRandomInRange(75, 125) / 100, // 0.751.25
4514+
noisePattern: Array.from(crypto.getRandomValues(new Uint8Array(64))),
45234515
headerVariations: [
45244516
'X-Client-Version', 'X-Session-ID', 'X-Request-ID', 'X-Timestamp', 'X-Signature',
45254517
'X-Secure', 'X-Encrypted', 'X-Protected', 'X-Safe', 'X-Anonymous', 'X-Private'
45264518
],
4527-
noiseIntensity: this.getUnbiasedRandomInRange(50, 150), // 50-150%
4528-
sizeMultiplier: this.getUnbiasedRandomInRange(75, 125) / 100, // 0.75-1.25
4529-
timingVariation: this.getUnbiasedRandomInRange(100, 1100) // 100-1100ms
4519+
noiseIntensity: this.getUnbiasedRandomInRange(50, 150), // 50150%
4520+
sizeMultiplier: this.getUnbiasedRandomInRange(75, 125) / 100,
4521+
timingVariation: this.getUnbiasedRandomInRange(100, 1100)
45304522
};
45314523
return mask;
45324524
}
45334525

4526+
45344527
// Security configuration - all features enabled by default
45354528
configureSecurityForSession() {
45364529
this._secureLog('info', '🔧 Configuring security - all features enabled by default');

0 commit comments

Comments
 (0)