CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2025-22234

The 73rd Byte: How a Spring Security Fix Created a Timing Leak

Alon Barad
Alon Barad
Software Engineer

Jan 23, 2026·5 min read·60 visits

Executive Summary (TL;DR)

Spring Security tried to fix a password truncation issue (CVE-2025-22228) by banning passwords longer than 72 bytes. However, they enforced this check too early in the authentication flow. By sending a 73+ byte password, attackers could trigger an immediate exception for non-existent users (bypassing the 'dummy' hash), while existing users took longer to process. This timing discrepancy allowed for reliable username enumeration.

A medium-severity timing attack vulnerability in Spring Security's DaoAuthenticationProvider. An improperly implemented length check for BCrypt passwords allowed attackers to bypass timing mitigations and enumerate usernames by analyzing response times.

The Hook: The Law of Unintended Consequences

Spring Security is the gold standard for Java authentication. But in early 2025, the maintainers learned a hard lesson in "fixing things until they break." This is the story of CVE-2025-22234, a vulnerability that proves the road to hell is paved with good intentions—and strict input validation.

It all started when someone realized the BCrypt algorithm has a fundamental limitation: it silently ignores any password characters beyond the 72nd byte. Spring decided to fix this "silent truncation" by throwing an error if a user provided a long password. Sounds reasonable, right? It's better to fail loud than to give a false sense of security.

Wrong. By throwing that error indiscriminately, they accidentally gave attackers a high-precision stopwatch and a map to every valid username in the database. It’s like installing a high-tech burglar alarm that screams "NOBODY IS HOME" the second someone touches the doorknob.

The Flaw: The 72-Byte Curse

To understand this bug, you have to understand the ancient curse of BCrypt. The algorithm has a hard limit: it only hashes the first 72 bytes of input. Anything after that is ghost data. In a previous patch (CVE-2025-22228), Spring Security decided to enforce this limit strictly.

The logic was added to the BCrypt class: if password.length > 72, throw an IllegalArgumentException. The problem is that authentication happens in two distinct contexts:

  1. Registration (Encoding): We definitely want to stop users from creating passwords that will be truncated.
  2. Login (Matching): We are just checking if the input matches the stored hash.

The developers applied the exception to both scenarios. This created a logic bomb inside DaoAuthenticationProvider, the component responsible for juggling user lookups and password checks.

The Code: The Smoking Gun

Let's look at DaoAuthenticationProvider. It tries to be clever to prevent timing attacks. If a user isn't found in the database, it runs a "dummy" hash operation so the request takes roughly the same amount of time as a successful lookup.

if (user == null) {
    // Run a dummy check to waste time and hide the fact the user is missing
    mitigateAgainstTimingAttack(authentication);
    throw new BadCredentialsException(...);
}

Inside mitigateAgainstTimingAttack, it calls the vulnerable BCrypt method. In version 6.4.4, the code looked like this:

private static String hashpw(byte passwordb[], String salt, boolean for_check) {
    // THE BUG: This throws immediately, before any CPU work is done
    if (passwordb.length > 72) {
        throw new IllegalArgumentException("password cannot be more than 72 bytes");
    }
    // ... expensive hashing loop that takes ~100ms ...
}

Do you see it? If I send a 73-byte password for a non-existent user, the "dummy" check crashes instantly due to the exception. It doesn't waste time. It exits.

However, if the user exists, the application loads the user details first, potentially checks the hash differently, or hits the exception later in the pipeline. This creates a massive timing gap.

The Exploit: Weaponizing the Stopwatch

This vulnerability allows for a classic Side-Channel Timing Attack. We can enumerate users by measuring how fast the server rejects us. Here is the attack chain:

  1. Identify Target: Find a Spring Security login form.
  2. Establish Baseline: Send a normal login request. Note the average response time (e.g., 150ms).
  3. The Probe: Send a login request with the username admin and a password string of 75 As.

The Results:

  • Result A (User NOT Found): The DaoAuthenticationProvider sees user == null. It calls mitigateAgainstTimingAttack. The BCrypt class sees 75 bytes and throws the exception immediately. Total time: ~5ms.
  • Result B (User FOUND): The provider loads the user from the DB. It proceeds to check the password. Even if it eventually fails, the DB lookup and object hydration take time. Total time: ~150ms.

> [!NOTE] > The difference between 5ms and 150ms is an eternity in network terms. It's trivially easy to distinguish, even with network jitter.

The Fix: Context is King

The fix, released in version 6.4.5 (and others), is elegant in its simplicity. The developers realized they needed to distinguish between creating a password and checking one.

The patched code introduces context awareness using the for_check boolean:

private static String hashpw(byte passwordb[], String salt, boolean for_check) {
    // FIXED: Only enforce length limit if we are NOT checking (i.e., we are encoding a new password)
    if (!for_check && passwordb.length > 72) {
        throw new IllegalArgumentException("password cannot be more than 72 bytes");
    }
    // Proceed with hashing (using first 72 bytes) to maintain timing consistency
    // ...
}

Now, if I send a long password for a ghost user, the system shrugs, proceeds to the expensive hashing loop (using the first 72 bytes), and returns in 150ms. The timing leak is plugged because the "dummy" calculation actually runs, ensuring User Found and User Not Found take the same amount of time.

Official Patches

SpringOfficial Advisory

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

Spring Security 6.4.4Spring Security 6.3.8Spring Security 6.2.10Spring Security 6.1.14Spring Security 6.0.16Spring Security 5.8.18Spring Security 5.7.16

Affected Versions Detail

Product
Affected Versions
Fixed Version
Spring Security
VMware
6.4.46.4.5
Spring Security
VMware
6.3.86.3.9
Spring Security
VMware
5.8.185.8.19
AttributeDetail
CWE IDCWE-208
Attack VectorNetwork
CVSS5.3 (Medium)
ImpactInformation Disclosure (Username Enumeration)
Exploit StatusPoC Available
Root CauseException thrown before constant-time operation

MITRE ATT&CK Mapping

T1589Gather Victim Identity Information
Reconnaissance
T1110Brute Force
Credential Access
CWE-208
Observable Timing Discrepancy

The application functions with a timing discrepancy, where the time taken to respond to a query varies based on the input, allowing an attacker to infer information.

Known Exploits & Detection

GitHubProof of concept discussed in issue tracker

Vulnerability Timeline

Vendor Advisory & Patch Released
2025-04-22
Published in NVD
2026-01-22

References & Sources

  • [1]Spring Security CVE-2025-22234 Advisory
  • [2]Context: The Preceding Vulnerability
Related Vulnerabilities
CVE-2025-22228

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•2 days ago•CVE-2026-9354
6.9

CVE-2026-9354: Arbitrary Mass Mention Bypass in NousResearch hermes-agent Slack and Mattermost Adapters

A vulnerability in the Slack and Mattermost platform adapters for NousResearch hermes-agent permits an unauthenticated remote attacker to execute arbitrary mass mentions. By leveraging prompt injection, an attacker can bypass output sanitization logic and trigger workspace-wide notification exhaustion.

Alon Barad
Alon Barad
24 views•6 min read
•2 days ago•CVE-2026-9306
6.3

CVE-2026-9306: Unauthenticated Insecure Direct Object Reference (IDOR) in QuantumNous new-api Midjourney Relay

CVE-2026-9306 is a critical unauthenticated Insecure Direct Object Reference (IDOR) vulnerability located in the QuantumNous new-api application, affecting versions up to and including 0.12.1. The flaw is caused by improper middleware ordering combined with a lack of object-level authorization checks. This allows remote, unauthenticated attackers to retrieve sensitive Midjourney images belonging to other users by supplying a valid task identifier.

Amit Schendel
Amit Schendel
8 views•5 min read
•3 days ago•GHSA-GGXF-37HM-9WQF
6.5

GHSA-GGXF-37HM-9WQF: Session Leakage via Unsafe Challenge Path Parsing in instagrapi

The instagrapi library prior to version 2.6.9 contains an improper input validation vulnerability within its challenge handling mechanism. Maliciously crafted server responses can manipulate the client into forwarding session cookies and credentials to an external attacker-controlled domain.

Amit Schendel
Amit Schendel
20 views•6 min read
•3 days ago•GHSA-QQQM-5547-774X
9.1

GHSA-QQQM-5547-774X: Unauthenticated Path Traversal in FileBrowser Quantum PATCH Handler

GHSA-QQQM-5547-774X is a critical path traversal vulnerability in the FileBrowser Quantum application, specifically within the Go backend package. The vulnerability resides in the HTTP handler responsible for processing bulk file modifications via the public API. Unauthenticated attackers can exploit an order-of-operations flaw in the path sanitization logic to bypass intended directory restrictions. This allows adversaries to arbitrarily read, move, and overwrite files on the underlying filesystem by supplying specially crafted HTTP PATCH requests.

Alon Barad
Alon Barad
5 views•6 min read
•3 days ago•CVE-2026-8723
5.3

CVE-2026-8723: Synchronous Denial of Service in qs npm Package via TypeError

The qs query string parsing and serialization library for Node.js is vulnerable to a synchronous Denial of Service (DoS) attack. The vulnerability manifests as a process-terminating TypeError when processing arrays with null or undefined elements under specific configuration parameters.

Amit Schendel
Amit Schendel
33 views•7 min read
•3 days ago•GHSA-7M8F-HGJQ-8GC9
7.5

GHSA-7M8F-HGJQ-8GC9: Pre-Authentication Denial of Service via Insecure Deserialization Order in aiosend

The aiosend library prior to version 3.0.6 contains a pre-authentication Denial of Service (DoS) vulnerability in its webhook handling mechanism. The software processes and deserializes incoming JSON payloads before verifying the cryptographic signature, allowing unauthenticated attackers to exhaust server CPU and memory resources by sending large, complex payloads.

Amit Schendel
Amit Schendel
3 views•6 min read