From 9ea12ddd1ac298ef3d7a15156b1ad4efd48c19df Mon Sep 17 00:00:00 2001 From: SachinAkash01 Date: Wed, 24 Sep 2025 05:06:19 +0530 Subject: [PATCH 1/3] [Automated] Update the native jar versions --- ballerina/Ballerina.toml | 6 +++--- ballerina/CompilerPlugin.toml | 2 +- ballerina/Dependencies.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index e7cf364b6..70c668b03 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "ftp" -version = "2.14.0" +version = "2.14.1" authors = ["Ballerina"] keywords = ["FTP", "SFTP", "remote file", "file transfer", "client", "service"] repository = "https://github.com/ballerina-platform/module-ballerina-ftp" @@ -45,5 +45,5 @@ path = "./lib/commons-lang3-3.18.0.jar" [[platform.java21.dependency]] groupId = "io.ballerina.stdlib" artifactId = "ftp-native" -version = "2.14.0" -path = "../native/build/libs/ftp-native-2.14.0.jar" +version = "2.14.1" +path = "../native/build/libs/ftp-native-2.14.1-SNAPSHOT.jar" diff --git a/ballerina/CompilerPlugin.toml b/ballerina/CompilerPlugin.toml index 5b1c8fbd2..ee7df9870 100644 --- a/ballerina/CompilerPlugin.toml +++ b/ballerina/CompilerPlugin.toml @@ -3,4 +3,4 @@ id = "ftp-compiler-plugin" class = "io.ballerina.stdlib.ftp.plugin.FtpCompilerPlugin" [[dependency]] -path = "../compiler-plugin/build/libs/ftp-compiler-plugin-2.14.0.jar" +path = "../compiler-plugin/build/libs/ftp-compiler-plugin-2.14.1-SNAPSHOT.jar" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 61c04c3a9..8cb9d8cc2 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -10,7 +10,7 @@ distribution-version = "2201.12.0" [[package]] org = "ballerina" name = "ftp" -version = "2.14.0" +version = "2.14.1" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, From 6d79fe38705b90eeb70808906d08d8beda2d1b97 Mon Sep 17 00:00:00 2001 From: SachinAkash01 Date: Wed, 24 Sep 2025 05:48:46 +0530 Subject: [PATCH 2/3] Fix the issue where the password isexposed in the error object --- .../tests/client_endpoint_negative_test.bal | 2 +- ballerina/tests/client_endpoint_test.bal | 2 +- .../tests/secure_client_endpoint_test.bal | 2 +- .../contractimpl/VfsClientConnectorImpl.java | 21 ++++++++++++------- .../server/util/FileTransportUtils.java | 15 +++++++------ .../io/ballerina/stdlib/ftp/util/FtpUtil.java | 10 ++++++--- 6 files changed, 31 insertions(+), 21 deletions(-) diff --git a/ballerina/tests/client_endpoint_negative_test.bal b/ballerina/tests/client_endpoint_negative_test.bal index 8223838d1..ce1f12fc5 100644 --- a/ballerina/tests/client_endpoint_negative_test.bal +++ b/ballerina/tests/client_endpoint_negative_test.bal @@ -61,7 +61,7 @@ public function testConnectionWithInvalidConfiguration() returns error? { public function testReadNonExistingFile() returns error? { stream|Error str = (clientEp)->get("/home/in/nonexisting.txt"); if str is Error { - test:assertEquals(str.message(), "Failed to read file: ftp://wso2:wso2123@127.0.0.1:21212/home/in/nonexisting.txt not found", + test:assertEquals(str.message(), "Failed to read file: ftp://wso2:***@127.0.0.1:21212/home/in/nonexisting.txt not found", msg = "Unexpected error during the `get` operation of an non-existing file."); } else { test:assertFail(msg = "Found a non-error response while accessing a non-existing file path"); diff --git a/ballerina/tests/client_endpoint_test.bal b/ballerina/tests/client_endpoint_test.bal index 9ded6c685..5676e4f5b 100644 --- a/ballerina/tests/client_endpoint_test.bal +++ b/ballerina/tests/client_endpoint_test.bal @@ -521,7 +521,7 @@ public function testDeleteFile() returns error? { } } else { test:assertEquals(str.message(), - "Failed to read file: ftp://wso2:wso2123@127.0.0.1:21212/home/in/test1.txt not found", + "Failed to read file: ftp://wso2:***@127.0.0.1:21212/home/in/test1.txt not found", msg = "Correct error is not given when the file is deleted." + str.message()); } } diff --git a/ballerina/tests/secure_client_endpoint_test.bal b/ballerina/tests/secure_client_endpoint_test.bal index 5f1e03df1..55005be7e 100644 --- a/ballerina/tests/secure_client_endpoint_test.bal +++ b/ballerina/tests/secure_client_endpoint_test.bal @@ -305,7 +305,7 @@ public function testSecureDeleteFileContent() returns error? { } } else { test:assertEquals(str.message(), - "Failed to read file: sftp://wso2:wso2123@127.0.0.1:21213/tempFile1.txt not found", + "Failed to read file: sftp://wso2:***@127.0.0.1:21213/tempFile1.txt not found", msg = "Correct error is not given when trying to get a non-existing file."); } } diff --git a/native/src/main/java/io/ballerina/stdlib/ftp/transport/client/connector/contractimpl/VfsClientConnectorImpl.java b/native/src/main/java/io/ballerina/stdlib/ftp/transport/client/connector/contractimpl/VfsClientConnectorImpl.java index d29148d06..6b83f0d72 100644 --- a/native/src/main/java/io/ballerina/stdlib/ftp/transport/client/connector/contractimpl/VfsClientConnectorImpl.java +++ b/native/src/main/java/io/ballerina/stdlib/ftp/transport/client/connector/contractimpl/VfsClientConnectorImpl.java @@ -44,6 +44,8 @@ import java.util.HashMap; import java.util.Map; +import static io.ballerina.stdlib.ftp.transport.server.util.FileTransportUtils.maskUrlPassword; + /** * Implementation for {@link VfsClientConnector} interface. */ @@ -68,8 +70,9 @@ public VfsClientConnectorImpl(Map config) fileURI = connectorConfig.get(FtpConstants.URI); path = fsManager.resolveFile(fileURI, opts); } catch (FileSystemException e) { + String safeUri = maskUrlPassword(fileURI); throw new RemoteFileSystemConnectorException("Error while connecting to the FTP server with URL: " - + (fileURI != null ? fileURI : ""), e.getCause()); + + (safeUri != null ? safeUri : ""), e.getCause()); } } @@ -94,7 +97,7 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP case MKDIR: if (fileObject.exists()) { throw new RemoteFileSystemConnectorException("Directory exists: " - + fileObject.getName().getURI()); + + maskUrlPassword(fileObject.getName().getURI())); } fileObject.createFolder(); break; @@ -130,7 +133,8 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP } } else { throw new RemoteFileSystemConnectorException( - "Failed to delete file: " + fileObject.getName().getURI() + " not found"); + "Failed to delete file: " + maskUrlPassword(fileObject.getName().getURI()) + + " not found"); } break; case RMDIR: @@ -141,7 +145,8 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP } } else { throw new RemoteFileSystemConnectorException( - "Failed to delete directory: " + fileObject.getName().getURI() + " not found"); + "Failed to delete directory: " + maskUrlPassword(fileObject.getName().getURI()) + + " not found"); } break; case RENAME: @@ -157,7 +162,7 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP fileObject.moveTo(finalPath); } else { throw new RemoteFileSystemConnectorException( - "The file at " + newPath.getURL().toString() + "The file at " + maskUrlPassword(newPath.getURL().toString()) + " already exists or it is a directory"); } } @@ -165,7 +170,8 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP } } else { throw new RemoteFileSystemConnectorException( - "Failed to rename file: " + fileObject.getName().getURI() + " not found"); + "Failed to rename file: " + maskUrlPassword(fileObject.getName().getURI()) + + " not found"); } break; case GET: @@ -180,7 +186,8 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP pathClose = false; } else { throw new RemoteFileSystemConnectorException( - "Failed to read file: " + fileObject.getName().getURI() + " not found"); + "Failed to read file: " + maskUrlPassword(fileObject.getName().getURI()) + + " not found"); } break; case SIZE: diff --git a/native/src/main/java/io/ballerina/stdlib/ftp/transport/server/util/FileTransportUtils.java b/native/src/main/java/io/ballerina/stdlib/ftp/transport/server/util/FileTransportUtils.java index f4f0a4181..84b2a755f 100644 --- a/native/src/main/java/io/ballerina/stdlib/ftp/transport/server/util/FileTransportUtils.java +++ b/native/src/main/java/io/ballerina/stdlib/ftp/transport/server/util/FileTransportUtils.java @@ -31,7 +31,6 @@ import java.time.Duration; import java.util.Locale; import java.util.Map; -import java.util.regex.Matcher; import java.util.regex.Pattern; import static io.ballerina.stdlib.ftp.util.FtpConstants.ENDPOINT_CONFIG_PREFERRED_METHODS; @@ -46,8 +45,8 @@ public final class FileTransportUtils { private FileTransportUtils() {} - private static final Pattern URL_PATTERN = Pattern.compile("[a-z]+://.*"); - private static final Pattern PASSWORD_PATTERN = Pattern.compile(":(?:[^/]+)@"); + private static final Pattern URL_PATTERN = Pattern.compile("^[a-z][a-z0-9+.-]*://", Pattern.CASE_INSENSITIVE); + private static final Pattern USERINFO_WITH_PASSWORD = Pattern.compile("://([^/@:]+):([^/@]*)@"); /** * A utility method for setting the relevant configurations for the file system in question. @@ -115,12 +114,12 @@ private static void setSftpOptions(Map options, FileSystemOption */ @ExcludeCoverageFromGeneratedReport public static String maskUrlPassword(String url) { - Matcher urlMatcher = URL_PATTERN.matcher(url); - if (urlMatcher.find()) { - Matcher pwdMatcher = PASSWORD_PATTERN.matcher(url); - return pwdMatcher.replaceFirst("\":***@\""); - } else { + if (url == null) { + return null; + } + if (!URL_PATTERN.matcher(url).find()) { return url; } + return USERINFO_WITH_PASSWORD.matcher(url).replaceFirst("://$1:***@"); } } diff --git a/native/src/main/java/io/ballerina/stdlib/ftp/util/FtpUtil.java b/native/src/main/java/io/ballerina/stdlib/ftp/util/FtpUtil.java index e5072c8a3..4d9f227b5 100644 --- a/native/src/main/java/io/ballerina/stdlib/ftp/util/FtpUtil.java +++ b/native/src/main/java/io/ballerina/stdlib/ftp/util/FtpUtil.java @@ -52,6 +52,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import static io.ballerina.stdlib.ftp.transport.server.util.FileTransportUtils.maskUrlPassword; import static io.ballerina.stdlib.ftp.util.FtpConstants.ENDPOINT_CONFIG_PREFERRED_METHODS; import static io.ballerina.stdlib.ftp.util.FtpConstants.FTP_ANONYMOUS_PASSWORD; import static io.ballerina.stdlib.ftp.util.FtpConstants.FTP_ANONYMOUS_USERNAME; @@ -151,14 +152,17 @@ public static Map getAuthMap(BMap config) { * @return an error which will be propagated to ballerina user. */ public static BError createError(String message, String errorTypeName) { - return ErrorCreator.createError(ModuleUtils.getModule(), errorTypeName, StringUtils.fromString(message), + String safeMessage = maskUrlPassword(message); + return ErrorCreator.createError(ModuleUtils.getModule(), errorTypeName, StringUtils.fromString(safeMessage), null, null); } public static BError createError(String message, Throwable cause, String errorTypeName) { - return ErrorCreator.createError(ModuleUtils.getModule(), errorTypeName, StringUtils.fromString(message), + String safeMessage = maskUrlPassword(message); + return ErrorCreator.createError(ModuleUtils.getModule(), errorTypeName, StringUtils.fromString(safeMessage), cause == null ? null : cause instanceof BError ? - (BError) cause : ErrorCreator.createError(StringUtils.fromString(cause.getMessage())), null); + (BError) cause : ErrorCreator.createError(StringUtils + .fromString(maskUrlPassword(cause.getMessage()))), null); } public static Throwable findRootCause(Throwable throwable) { From 3c20e24322c7898fd35da104c570c582ac2bcf34 Mon Sep 17 00:00:00 2001 From: Niveathika Date: Wed, 24 Sep 2025 09:57:31 +0530 Subject: [PATCH 3/3] Update changelog --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 1952f2d65..f790f112a 100644 --- a/changelog.md +++ b/changelog.md @@ -10,7 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Fixed - [Fix the issue where the FTP URL is improperly formatted for the jail-break scnenarios](https://github.com/ballerina-platform/ballerina-library/issues/8267) - +- Fix exposed passwords in logs ## [2.14.0] - 2025-08-21