Skip to content

VNX-342: Predictable Exact Value from Previous Values

Detects secrets that are the next value of a counter (sessionId++, ++lastToken, incrementAndGet(), atomic.AddInt64, next(counter), .succ) when the counter is named for a secret or its result is stored, returned or set as a cookie value of one. Java, Kotlin, Python, JavaScript/TypeScript, PHP, Ruby and Go.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-342
Severity Medium
SARIF level warning
Kind sast
Languages Java, Kotlin, Python, JavaScript / TypeScript, PHP, Ruby, Go
CWE CWE-342
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C
Tags randomness predictable cwe-342
Source internal/sast/rules/vnx-342.rego

Overview

VNX-342 maps to CWE-342: Predictable Exact Value from Previous Values. A session id, reset code or token that is the previous one plus one is not a secret: a user who receives their own value knows the value issued just before and the one that will be issued next.

The rule reports an increment (++x, x++, x += 1, x + 1, incrementAndGet()/getAndIncrement()/addAndGet(), Go atomic.AddInt64/AddUint64 and .Add(1), Python next(counter), Ruby .succ/.next) of a variable named as a counter or previous value (count, ctr, seq, last, prev, next, serial, latest, max, id, num) or for a secret, when:

  • the incremented variable is itself named for a secret ($_SESSION['last_session_id']++, captchaId++), or
  • its result is stored under, returned as or set as the cookie value of a secret (token, password, session id, reset/confirmation/invite code, OTP, CSRF, API key) on the same line, or
  • a standalone increment is followed within four lines by a use of the variable as a secret, or
  • the result is assigned to a variable that reaches a secret within six lines.

What Gets Flagged

// FLAGGED: the session cookie is a counter
$_SESSION['next_session_id']++;
setcookie("appSession", $_SESSION['next_session_id']);
// FLAGGED
public String newSessionId() {
    return Long.toString(counter.incrementAndGet());
}
String resetToken = String.valueOf(++lastToken);
# FLAGGED
session_id = str(next(_ids))
// FLAGGED
id := atomic.AddInt64(&sessionCounter, 1)
return strconv.FormatInt(id, 10)

What Is Not Flagged

  • Anonymous loop variables (i++, n += 1) and loop headers.
  • Counters used as nonces, IVs, JWT ids or message sequence numbers: they need uniqueness, not secrecy. HOTP/HMAC over a counter.
  • Counts, indexes, attempts and other bookkeeping names (tokenCount++, $_SESSION['login_attempts']++, this.tokenPos++), order and request ids.
  • A line that also draws from a CSPRNG, test files, and the pattern in comments or string literals.

A secret that mixes a counter with the clock is also reported by VNX-341.

Remediation

  1. Generate each secret independently with a CSPRNG: secrets.token_urlsafe(), crypto.randomBytes(), random_bytes(), SecureRandom, crypto/rand, SecureRandom.hex.
  2. Keep sequential ids for database keys and ordering, and never hand them out as credentials.
  3. For confirmed false positives, add a # vulnetix-ignore: VNX-342 comment on the line.

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-342
// nosec vnx-342

Or record an ignore rule: vulnetix ignore add --rule vnx-342 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-342.rego, cli/internal/sast/docs/vnx-342.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.