While building SCIP — a supply chain platform with 90+ Spring Boot REST endpoints — I was boundary-testing the auth flow when I noticed something that shouldn't have been possible.
java
BCrypt.matches(null, hash)
This was returning true.
Not for a specific hash. Not under some obscure edge case. Any account with a null password field — a soft-deleted user, a malformed request, anything that left password unset — could authenticate with literally any password typed in.
Why Standard Tests Never Caught This
Happy-path test suites check valid credentials against valid hashes. That's the test everyone writes. Nobody writes a test for "what happens when the password field itself is missing," because on the surface, that feels like an edge case too obscure to matter.
It surfaced only because I deliberately tested null and malformed inputs against a security-critical comparison, instead of trusting the library to handle them safely by default.
Why This Mattered More Than a Normal Bug
Auth sits at the trust boundary of the entire application. A bypass there doesn't compromise one feature — it undermines the security model of everything built on top of it. A bug in, say, a reporting dashboard is contained. A bug in auth is not.
The Fix
Simple once found — a null guard before BCrypt ever runs:
java
if (password == null || password.isBlank()) {
throw new SecurityException("Invalid credentials");
}
if (!BCrypt.matches(password, hash)) {
throw new UnauthorizedException("Invalid credentials");
}
I write about AI system architecture and quality engineering at chaitrishodaya.com — including the real bugs, not just the finished results.
security, java, springboot, testing
Top comments (0)