CVE-2026-40975
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Spring Boot is an open-source framework from the Spring team that simplifies building production-grade Java applications by providing opinionated auto-configuration, embedded servlet containers, and convention-based starters. A medium-severity vulnerability (CVE-2026-40975) has been identified in Spring Boot's RandomValuePropertySource, the built-in property source that resolves the ${random.*} placeholders available in application.properties and application.yml.
Before the fix, RandomValuePropertySource seeded its backing generator with new java.util.Random(). java.util.Random is a 48-bit linear congruential generator, not a cryptographic PRNG, and its output stream can be recovered from a small number of observed values. The impact is focused on ${random.value}: values produced by ${random.value} are not suitable for use as secrets. ${random.uuid} is NOT affected because UUID.randomUUID() internally uses SecureRandom. ${random.int} and ${random.long} should never be used for secrets in any version because they resolve to a single numeric value with a predictable range, regardless of PRNG strength.
Per OWASP: "Standard pseudo-random number generators cannot withstand cryptographic attacks. Insecure randomness errors occur when a function that can produce predictable values is used as a source of randomness in a security-sensitive context." The weakness in Spring Boot is exactly this class of bug: a general-purpose PRNG was used to back a property placeholder that tutorials and documentation frequently pointed developers at when they needed to bootstrap a secret.
This issue affects Spring Boot >=1.0.0 <=3.5.13 and >=4.0.0 <=4.0.5. The vulnerable new Random() pattern has been present in RandomValuePropertySource since Spring Boot 1.0, so every release prior to the 3.5.14 / 4.0.6 fixes is affected.
Details
Module Info
- Product: Spring Boot
- Affected packages: spring-boot
- Affected versions: >=1.0.0 <=3.5.13, >=4.0.0 <=4.0.5
- GitHub repository: https://github.com/spring-projects/spring-boot
- Published packages: https://central.sonatype.com/artifact/org.springframework.boot/spring-boot
- Package manager: maven
- Fixed in:
- NES for Spring Boot 1.5.x, 2.5.x, 2.7.x, 3.2.x, 3.3.x, 3.4.x
- OSS Spring Boot 3.5.14, 4.0.6
Vulnerability Info
RandomValuePropertySource lives in the org.springframework.boot.env package (pre-2.0 it lived in org.springframework.boot.context.config) and is wired into every Spring Boot ConfigurableEnvironment at startup. It resolves four families of placeholders:
- ${random.int} / ${random.int(max)} / ${random.int[min,max]}: a single int
- ${random.long} / ${random.long(max)} / ${random.long[min,max]}: a single long
- ${random.uuid}: a UUID.randomUUID().toString()
- ${random.value} (and any other random.<name> that does not match the above): 16 random bytes hex-encoded as a 32-character lowercase string
The class extends PropertySource<Random> and stores its generator as the source value. Before the fix, the constructor built that generator with new Random():
public RandomValuePropertySource(String name) {
super(name, new Random());
}
java.util.Random has a 48-bit internal state and is seeded from System.nanoTime() XORed with a process-wide seed uniquifier. An attacker who observes roughly 128 bits of consecutive output (two 32-bit nextInt values, or a single 16-byte nextBytes fill that backs ${random.value}) can brute-force the 48-bit seed and reproduce every past and future value from the same Random instance. This is a well-documented property of java.util.Random and is why the java.security package ships the unrelated SecureRandom class for cryptographic contexts.
For ${random.value} specifically, the path getRandomBytes() fills 16 bytes and hex-encodes them:
private Object getRandomBytes() {
byte[] bytes = new byte[16];
getSource().nextBytes(bytes);
return HexFormat.of().withLowerCase().formatHex(bytes);
}
Any application that wired ${random.value} into a secret (for example spring.security.user.password=${random.value}, a default admin token emitted at first startup, a session signing key persisted at boot, or a bootstrap credential written into a generated configuration file) published a value that appears random but is in fact drawn from a recoverable PRNG. An attacker who sees one such value can predict the next ${random.value} issued by the same JVM, and can also predict any subsequent ${random.int} / ${random.long} draws from the same property source. This yields partial confidentiality and integrity impact, matching the published CVSS vector AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N.
${random.uuid} is not on this code path. It is handled by UUID.randomUUID().toString(), which internally lazy-initialises a static SecureRandom the first time it is called, and is therefore a cryptographically sound source of randomness regardless of the RandomValuePropertySource backing generator.
Because SecureRandom extends java.util.Random, the field type on PropertySource<Random> is unchanged and every downstream call, getSource().nextInt(...), getSource().nextLong(...), getSource().nextBytes(...), now dispatches into the cryptographic PRNG. No API surface changes, no property semantics change, and ${random.uuid} behaviour is identical.
Mitigation
Only recent versions of Spring Boot receive community support and updates. See Spring Boot Support page for the current OSS support policy. Earlier lines (1.5.x, 2.5.x, 3.2.x) have been End-of-Life for longer and will not receive any public patch for this issue at all. We recommend the following courses of action:
- Upgrade to a currently-supported Spring Boot release (3.5.14 or 4.0.6 or later).
- Adopt HeroDevs Never-Ending Support for Spring Boot to receive the fix on 1.5.x, 2.5.x, 2.7.x, 3.2.x, 3.3.x, and 3.4.x while planning a longer-term upgrade. See NES for Spring for details.
Independent of the upgrade path, any application that previously wired ${random.value} into a long-lived secret (a stored password, a signing key, an API token, an encryption-at-rest key) should rotate that secret after upgrading, because the value that is already in production was generated by the weak PRNG. ${random.int} and ${random.long} should never be used as secrets under any Spring Boot version, because a single integer drawn from any range small enough to fit in 32 or 64 bits does not carry enough entropy to stand up to brute force regardless of the PRNG used to produce it; prefer ${random.uuid} or an external key-management system for secret generation.
Credits
No external finder is credited in the upstream advisory as of April 24, 2026.