Skip to content

🛡️ Sentinel: [MEDIUM] Fix weak random number generation#320

Merged
beenycool merged 2 commits intomasterfrom
fix-weak-random-generation-4636760693768330986
Mar 20, 2026
Merged

🛡️ Sentinel: [MEDIUM] Fix weak random number generation#320
beenycool merged 2 commits intomasterfrom
fix-weak-random-generation-4636760693768330986

Conversation

@beenycool
Copy link
Copy Markdown
Owner

@beenycool beenycool commented Mar 19, 2026

🚨 Severity: MEDIUM
💡 Vulnerability: Math.random() was being used for generating a uniqueness nonce in Redis and jitter offsets for retry delays. Math.random() is not cryptographically secure and produces predictable pseudo-random sequences.
🎯 Impact: Attackers could potentially predict nonces or calculate exact retry intervals for timing analysis.
🔧 Fix: Replaced Math.random() with randomBytes and randomInt from the built-in node:crypto library to enforce CSPRNG.
✅ Verification: Run cd backend && pnpm test. All tests should pass and Math.random() should no longer be used for these security or infrastructure logic points.


PR created automatically by Jules for task 4636760693768330986 started by @beenycool

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced randomness generation for retry delays and API call tracking using cryptographically secure methods.

@google-labs-jules
Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 19, 2026

Walkthrough

This PR replaces insecure Math.random() calls with cryptographically strong randomness from node:crypto. Changes include updating jitter delay calculation in the Hypixel service and nonce generation in the HypixelTracker service, with a security finding documented in the sentinel log.

Changes

Cohort / File(s) Summary
Security Documentation
.jules/sentinel.md
Added sentinel entry documenting a security vulnerability where Math.random() was used for Redis nonce and retry jitter generation, with prevention guidance to use cryptographically secure randomness.
Backend Service Updates
backend/src/services/hypixel.ts, backend/src/services/hypixelTracker.ts
Replaced weak randomness with secure randomness: jitterDelay() now uses randomInt() for integer jitter, and buildRedisRollingMember() now uses randomBytes() for nonce generation.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 With crypto so strong, our nonces now shine,
No more Math.random() by design,
Bytes and integers, secure and true,
From node:crypto, the better brew! 🔐

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly relates to the main change: replacing weak Math.random() with cryptographically secure randomness from node:crypto in security-sensitive contexts.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-weak-random-generation-4636760693768330986
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a medium-severity security vulnerability by replacing instances of Math.random() with cryptographically secure random number generation methods from Node.js's crypto module. This change significantly enhances the security posture of the application by preventing potential predictability of nonces used in Redis tracking and jitter offsets for retry delays, thereby mitigating risks of timing attacks or nonce prediction.

Highlights

  • Enhanced Security: Replaced Math.random() with cryptographically secure random number generators (randomBytes, randomInt) from node:crypto to address a medium-severity vulnerability.
  • Improved Jitter Calculation: Updated the jitterDelay function in hypixel.ts to use randomInt for more secure and unpredictable retry delay offsets.
  • Secure Redis Nonce Generation: Modified hypixelTracker.ts to use randomBytes for generating unique nonces in Redis, preventing predictability and potential timing attacks.
  • Documentation Update: Added a new entry to the sentinel.md security documentation detailing the weak random number generation vulnerability and its prevention.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly addresses the use of weak random number generation by replacing all instances of Math.random() with cryptographically secure alternatives from the node:crypto module. The implementation for generating jitter delays and uniqueness nonces is sound and effectively mitigates the described security vulnerability. The changes are well-executed and no issues were found.

const min = Math.max(0, HYPIXEL_RETRY_DELAY_MIN_MS);
const max = Math.max(min, HYPIXEL_RETRY_DELAY_MAX_MS);
return min + Math.random() * (max - min);
return max > min ? randomInt(min, max + 1) : min;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: Behavioral change in jitter range

The original code used Math.random() * (max - min) which returns a float in [0, max-min), making the result [min, max) - exclusive on max.

The new code uses randomInt(min, max + 1) which returns integers in [min, max] - inclusive on max.

This means the configured maximum retry delay is now achievable (previously it was never exactly reached). This is a minor behavioral difference and arguably more correct, but worth noting.

@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot Bot commented Mar 19, 2026

Code Review Summary

Status: 1 Suggestion Found | Recommendation: Merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
backend/src/services/hypixel.ts 171 Behavioral change in jitter range - see inline comment
Other Observations (not in diff)

No other issues found. The fix is complete - verified no remaining Math.random() calls in backend source code.

Files Reviewed (3 files)
  • .jules/sentinel.md - Documentation update (no code issues)
  • backend/src/services/hypixel.ts - 1 suggestion
  • backend/src/services/hypixelTracker.ts - No issues

Summary: The security fix is sound. Math.random() has been replaced with cryptographically secure alternatives (randomInt and randomBytes from node:crypto). The single suggestion is minor and does not block merge.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/src/services/hypixel.ts`:
- Around line 168-171: The jitterDelay function can call randomInt with non-safe
or out-of-range values from HYPIXEL_RETRY_DELAY_MIN_MS /
HYPIXEL_RETRY_DELAY_MAX_MS causing a RangeError; validate and sanitize those
env-derived bounds before calling randomInt. In jitterDelay, coerce both
HYPIXEL_RETRY_DELAY_MIN_MS and HYPIXEL_RETRY_DELAY_MAX_MS to integers, ensure
Number.isSafeInteger for min and max, clamp them to a safe non-negative range
(e.g., at least 0 and no greater than Number.MAX_SAFE_INTEGER or a reasonable
upper limit), ensure max >= min (swap or set max = min), and only then call
randomInt(min, max + 1); if validation fails, fall back to a safe default delay
or return the sanitized min.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 08d9fd00-e9ff-47b2-b9e0-ee4823c6ce47

📥 Commits

Reviewing files that changed from the base of the PR and between 03e9c85 and 21559f8.

📒 Files selected for processing (3)
  • .jules/sentinel.md
  • backend/src/services/hypixel.ts
  • backend/src/services/hypixelTracker.ts

Comment on lines 168 to +171
function jitterDelay(): number {
const min = Math.max(0, HYPIXEL_RETRY_DELAY_MIN_MS);
const max = Math.max(min, HYPIXEL_RETRY_DELAY_MAX_MS);
return min + Math.random() * (max - min);
return max > min ? randomInt(min, max + 1) : min;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify retry delay sources and lack/presence of bounds before randomInt usage.
rg -n -C3 'function jitterDelay|randomInt\(' backend/src/services/hypixel.ts
rg -n -C3 'HYPIXEL_RETRY_DELAY_MIN_MS|HYPIXEL_RETRY_DELAY_MAX_MS|parseIntEnv' backend/src/config.ts

Repository: beenycool/bedwars-level-head

Length of output: 6768


🏁 Script executed:

# Get the full parseIntEnv implementation
sed -n '221,240p' backend/src/config.ts

Repository: beenycool/bedwars-level-head

Length of output: 510


🏁 Script executed:

# Check what randomInt is and where it's imported from
rg -n 'import.*randomInt|from.*randomInt' backend/src/services/hypixel.ts

Repository: beenycool/bedwars-level-head

Length of output: 114


🏁 Script executed:

# See if there are any existing bounds/validation applied to HYPIXEL_RETRY_DELAY values elsewhere
rg -n -B5 -A5 'HYPIXEL_RETRY_DELAY' backend/src/config.ts

Repository: beenycool/bedwars-level-head

Length of output: 762


🌐 Web query:

Node.js crypto.randomInt constraints RangeError limits

💡 Result:

The Node.js crypto.randomInt([min,] max[, callback]) function generates a cryptographically secure random integer n such that min <= n < max (min defaults to 0 if omitted). It throws a RangeError in these cases: - min or max is not a safe integer (Number.isSafeInteger(min/max) must be true). - max <= min. Error: "The value of 'max' is out of range. It must be greater than the value of 'min' (X). Received Y." - The range (max - min) exceeds 2^48 - 1 (0xFFFFFFFFFFFF, or 281474976710655). Error: "The value of 'max-min' is out of range. It must be <= 281474976710655. Received Z." These constraints ensure uniform distribution without modulo bias, using up to 6 random bytes internally (max 48 bits). Added in Node.js v14.10.0 / v12.19.0. Current as of Node.js v25.x (2026). For larger ranges, use BigInt version or crypto.randomBytes manually.

Citations:


Guard randomInt inputs to prevent runtime RangeError on misconfigured env values.

At Line 171, randomInt(min, max + 1) throws RangeError if env-derived bounds are not safe integers (Number.isSafeInteger() must be true) or exceed the allowed range. The current code applies Math.max(0, ...) but lacks validation for safe integer bounds, turning misconfigured env values into hard crashes instead of graceful retry delays.

🔧 Proposed hardening
 function jitterDelay(): number {
+  const MAX_TIMEOUT_MS = 2_147_483_647; // setTimeout upper bound
+  const toSafeDelay = (value: number): number => {
+    if (!Number.isSafeInteger(value)) return 0;
+    return Math.min(MAX_TIMEOUT_MS, Math.max(0, value));
+  };
+
-  const min = Math.max(0, HYPIXEL_RETRY_DELAY_MIN_MS);
-  const max = Math.max(min, HYPIXEL_RETRY_DELAY_MAX_MS);
+  const min = toSafeDelay(HYPIXEL_RETRY_DELAY_MIN_MS);
+  const max = Math.max(min, toSafeDelay(HYPIXEL_RETRY_DELAY_MAX_MS));
   return max > min ? randomInt(min, max + 1) : min;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/src/services/hypixel.ts` around lines 168 - 171, The jitterDelay
function can call randomInt with non-safe or out-of-range values from
HYPIXEL_RETRY_DELAY_MIN_MS / HYPIXEL_RETRY_DELAY_MAX_MS causing a RangeError;
validate and sanitize those env-derived bounds before calling randomInt. In
jitterDelay, coerce both HYPIXEL_RETRY_DELAY_MIN_MS and
HYPIXEL_RETRY_DELAY_MAX_MS to integers, ensure Number.isSafeInteger for min and
max, clamp them to a safe non-negative range (e.g., at least 0 and no greater
than Number.MAX_SAFE_INTEGER or a reasonable upper limit), ensure max >= min
(swap or set max = min), and only then call randomInt(min, max + 1); if
validation fails, fall back to a safe default delay or return the sanitized min.

@beenycool beenycool merged commit 55ab019 into master Mar 20, 2026
3 checks passed
@beenycool beenycool deleted the fix-weak-random-generation-4636760693768330986 branch March 20, 2026 09:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant