Why Cursor Keeps Generating Insecure Random Session Tokens (CWE-330)
AI editors keep generating tokens with Math.random(), which is not cryptographically secure. Here is why it happens and how to fix it with crypto.randomBytes.
SafeWeave Team
TL;DR
- AI editors default to Math.random() for tokens because that's what nearly every tutorial and StackOverflow answer uses
- Math.random() is not cryptographically secure, so tokens built from it can be predicted or brute-forced
- Swap in crypto.randomBytes or crypto.randomUUID for anything security-sensitive
I was reviewing a password reset flow Cursor had scaffolded for a side project last week. The endpoint looked clean. Route, validation, database call, all fine. Then I got to the token generation line and stopped.
function generateResetToken() {
return Math.random().toString(36).substring(2); // not safe for this
}
This function generates the token that gets emailed to a user to reset their password. Anyone who can predict or narrow down the output space can hijack an account without ever touching the password field.
The Problem With Math.random()
Math.random() is a pseudo-random number generator built for things like shuffling an array or picking a random UI color. It is not built to resist an attacker. Its internal state can, in some engines, be recovered from a handful of outputs, and even without that, the output space from .toString(36).substring(2) is small enough to be practical to brute-force for a reset token that's valid for an hour.
This isn't a Cursor-specific bug. Claude Code and Copilot reproduce the exact same pattern when you ask for "a function to generate a random token" or "a random ID for this record."
Catch these vulnerabilities automatically with SafeWeave
SafeWeave runs 8 security scanners in parallel — SAST, secrets, dependencies, IaC, containers, DAST, license, and posture — right inside your AI editor. One command, zero config.
Start Scanning FreeTry SafeWeave in 30 seconds
npx safeweave-mcp
Works with Cursor, Claude Code, Windsurf, and VS Code. No signup required for the free tier — 3 scanners, unlimited scans.
Why This Keeps Happening
Go search "generate random string javascript." The first ten results almost all use Math.random(). They're not wrong for what they're demonstrating. If you're building a demo, a placeholder key for a React list, or a coin flip, Math.random() is completely fine.
The problem is that AI editors don't know the difference between a random string for a UI key and a random string that guards account access. They've seen millions of examples of the first pattern used to solve both problems, because most tutorials never separate the two use cases. The model reproduces the most common pattern it's seen for "generate random string," and that pattern was optimized for simplicity, not security.
The Fix
const crypto = require('crypto');
function generateResetToken() {
return crypto.randomBytes(32).toString('hex'); // safe
}
// or, for a simple unique ID:
const token = crypto.randomUUID(); // safe
Python has the same trap with random.randint() or random.choice() for tokens. Use the secrets module instead:
import secrets
token = secrets.token_hex(32) # safe
The rule of thumb: if the value grants access, proves identity, or gets used as a secret, it needs to come from a cryptographically secure source. If it's just for display or non-security uniqueness, Math.random() is still fine.
We built SafeWeave for exactly this. It hooks into Cursor and Claude Code as an MCP server and flags insecure randomness patterns like this one before you move on to the next file. A grep for Math.random() near words like "token," "password," or "session" catches most of it too, if you'd rather do it by hand.
Secure your AI-generated code with SafeWeave
8 security scanners running in parallel, right inside your AI editor. SAST, secrets, dependencies, IaC, containers, DAST, license compliance, and security posture — all in one command.
No credit card required · 3 scanners free forever · Runs locally on your machine