Why AI tools produce this: AI coding tools generate this anti-pattern by default, it appears in a large share of AI-written auth code.
Why this matters
Its name indicates a token, secret, key, password, nonce, OTP, or salt. math/rand is a deterministic PRNG: its output is predictable and an attacker who observes enough values can recover the seed and forecast every future token. For OAuth/OIDC this means forgeable state values, guessable authorization codes, and predictable refresh tokens.
Use crypto/rand instead: allocate a byte slice and fill it with rand.Read(b) (from crypto/rand), then hex- or base64url-encode it. Never derive a credential from math/rand.
package mainimport ( crand "crypto/rand" "encoding/hex" "fmt" "math/rand")// Secure: token comes from crypto/rand via rand.Read, not math/rand.func makeToken() string { b := make([]byte, 32) // ok: auth.go.flow.weak-rand _, _ = crand.Read(b) return hex.EncodeToString(b)}// Non-secret use of math/rand: a loop index / jitter. Not flagged.func pickIndex() int { // ok: auth.go.flow.weak-rand i := rand.Intn(10) return i}// Non-secret use: retry backoff jitter.func backoff() int { // ok: auth.go.flow.weak-rand delay := rand.Intn(500) return delay}func main() { fmt.Println(makeToken(), pickIndex(), backoff())}
Suppressing this rule
If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.