Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.plugin.version}</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>

Expand All @@ -82,6 +92,11 @@
<groupId>org.wso2.carbon.identity.framework</groupId>
<artifactId>org.wso2.carbon.identity.event</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ public static String[] getMaskedArraysOfValues(String[] values) {
*/
public static String getSanitizedErrorMessage(String errorMessage, String userName) {

if (LoggerUtils.isLogMaskingEnable && errorMessage.contains(userName)) {
if (LoggerUtils.isLogMaskingEnable && StringUtils.isNotBlank(errorMessage)
&& StringUtils.isNotBlank(userName) && errorMessage.contains(userName)) {
return errorMessage.replace(userName, LoggerUtils.getMaskedContent(userName));
}
return errorMessage;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.identity.central.log.mgt.utils;

import org.testng.annotations.AfterMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;

/**
* Unit tests for {@link LoggerUtils#getSanitizedErrorMessage(String, String)}.
*
*/
public class LoggerUtilsTest {

@AfterMethod
public void resetMaskingFlag() {

LoggerUtils.isLogMaskingEnable = false;
}

/**
* Core regression: masking enabled + null/blank/empty userName must NOT throw and must return
* the message unchanged. Before the fix this threw NPE ("s is null") inside String.contains.
*/
@Test(dataProvider = "blankUserNames")
public void testBlankUserNameReturnsMessageUnchanged(String userName) {

LoggerUtils.isLogMaskingEnable = true;
String errorMessage = "Some error for admin.";
assertEquals(LoggerUtils.getSanitizedErrorMessage(errorMessage, userName), errorMessage,
"Blank userName must return the original error message unchanged.");
}

@DataProvider(name = "blankUserNames")
public Object[][] blankUserNames() {

return new Object[][]{{""}, {" "}, {null}};
}

/**
* Masking disabled: null userName must still not throw and the message is returned as-is.
*/
@Test
public void testNullUserNameWithMaskingDisabledDoesNotThrow() {

LoggerUtils.isLogMaskingEnable = false;
String errorMessage = "Persisted access token data not found.";
assertEquals(LoggerUtils.getSanitizedErrorMessage(errorMessage, null), errorMessage,
"Masking disabled must return the original message unchanged.");
}

/**
* Existing behavior preserved: masking enabled and the userName present in the message ->
* the username is masked. Pattern (?<=.).(?=.) masks all but the first and last char.
*/
@Test
public void testUserNamePresentIsMaskedWhenMaskingEnabled() {

LoggerUtils.isLogMaskingEnable = true;
String userName = "admin";
String errorMessage = "Login failed for user admin in tenant carbon.super";
String sanitized = LoggerUtils.getSanitizedErrorMessage(errorMessage, userName);
assertFalse(sanitized.contains(userName),
"Raw username must not remain in the sanitized message.");
assertEquals(sanitized, "Login failed for user a***n in tenant carbon.super",
"Username must be masked with the first/last char retained.");
}

/**
* Masking enabled but the userName is not contained in the message -> message returned as-is.
*/
@Test
public void testUserNameNotPresentReturnsMessageUnchanged() {

LoggerUtils.isLogMaskingEnable = true;
String errorMessage = "Persisted access token data not found.";
assertEquals(LoggerUtils.getSanitizedErrorMessage(errorMessage, "admin"), errorMessage,
"When the username is absent the message must be unchanged.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com).
~
~ WSO2 LLC. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="central-log-mgt">
<test name="central-log-mgt-tests">
<classes>
<class name="org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtilsTest"/>
</classes>
</test>
</suite>