SecurityJul 23, 2026 · 2 min read

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.

SW

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 Free

Try 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