This is an automated email from the ASF dual-hosted git repository.

lprimak pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/shiro.git

commit ecd3abad2a7f663f43d0aab74ff6eded16ebb49f
Author: lprimak <[email protected]>
AuthorDate: Wed Oct 21 11:34:04 2026 -0500

    bugfix: ensure passwordsMatch method returns false for null or empty saved 
credentials
---
 .../org/apache/shiro/authc/credential/DefaultPasswordService.java | 6 +++---
 .../apache/shiro/authc/credential/SimpleCredentialsMatcher.java   | 5 +++++
 .../shiro/authc/credential/DefaultPasswordServiceTest.groovy      | 8 ++++----
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git 
a/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java
 
b/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java
index 95d88038c..4ec9db140 100644
--- 
a/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java
+++ 
b/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java
@@ -107,7 +107,7 @@ public class DefaultPasswordService implements 
HashingPasswordService {
         ByteSource plaintextBytes = createByteSource(plaintext);
 
         if (saved == null || saved.isEmpty()) {
-            return plaintextBytes == null || plaintextBytes.isEmpty();
+            return false;
         } else {
             if (plaintextBytes == null || plaintextBytes.isEmpty()) {
                 return false;
@@ -185,8 +185,8 @@ public class DefaultPasswordService implements 
HashingPasswordService {
     public boolean passwordsMatch(Object submittedPlaintext, String saved) {
         ByteSource plaintextBytes = createByteSource(submittedPlaintext);
 
-        if (saved == null || saved.length() == 0) {
-            return plaintextBytes == null || plaintextBytes.isEmpty();
+        if (saved == null || saved.isEmpty()) {
+            return false;
         } else {
             if (plaintextBytes == null || plaintextBytes.isEmpty()) {
                 return false;
diff --git 
a/core/src/main/java/org/apache/shiro/authc/credential/SimpleCredentialsMatcher.java
 
b/core/src/main/java/org/apache/shiro/authc/credential/SimpleCredentialsMatcher.java
index 9350f0ea0..5073cece6 100644
--- 
a/core/src/main/java/org/apache/shiro/authc/credential/SimpleCredentialsMatcher.java
+++ 
b/core/src/main/java/org/apache/shiro/authc/credential/SimpleCredentialsMatcher.java
@@ -99,6 +99,11 @@ public class SimpleCredentialsMatcher extends CodecSupport 
implements Credential
      * @return {@code true} if the {@code tokenCredentials} are equal to the 
{@code accountCredentials}.
      */
     protected boolean equals(Object tokenCredentials, Object 
accountCredentials) {
+        if (accountCredentials == null
+                || (isByteSource(accountCredentials) && 
toBytes(accountCredentials).length == 0)) {
+            // an empty or missing stored credential never matches anything
+            return false;
+        }
         if (LOGGER.isDebugEnabled() && tokenCredentials != null) {
             LOGGER.debug("Performing credentials equality check for 
tokenCredentials of type ["
                     + tokenCredentials.getClass().getName() + " and 
accountCredentials of type ["
diff --git 
a/core/src/test/groovy/org/apache/shiro/authc/credential/DefaultPasswordServiceTest.groovy
 
b/core/src/test/groovy/org/apache/shiro/authc/credential/DefaultPasswordServiceTest.groovy
index 3cf1256ba..ef46ce5fc 100644
--- 
a/core/src/test/groovy/org/apache/shiro/authc/credential/DefaultPasswordServiceTest.groovy
+++ 
b/core/src/test/groovy/org/apache/shiro/authc/credential/DefaultPasswordServiceTest.groovy
@@ -72,10 +72,10 @@ class DefaultPasswordServiceTest {
     @Test
     void testPasswordsMatchWithNullOrEmpty() {
         def service = createSha256Service()
-        assertTrue service.passwordsMatch(null, (String) null)
-        assertTrue service.passwordsMatch(null, (Hash) null)
-        assertTrue service.passwordsMatch("", (String) null)
-        assertTrue service.passwordsMatch(null, "")
+        assertFalse service.passwordsMatch(null, (String) null)
+        assertFalse service.passwordsMatch(null, (Hash) null)
+        assertFalse service.passwordsMatch("", (String) null)
+        assertFalse service.passwordsMatch(null, "")
         assertFalse service.passwordsMatch(null, "12345")
         assertFalse service.passwordsMatch(null, new Sha384Hash("test"))
     }

Reply via email to