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

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


The following commit(s) were added to refs/heads/main by this push:
     new 1a37111088 [SONAR] fix security hotspots (#8705)
1a37111088 is described below

commit 1a371110886d708f6fa39aba1338d60fa7010587
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Wed Sep 30 17:10:53 2026 +0200

    [SONAR] fix security hotspots (#8705)
    
    * [SONAR] fix security hotspots
    
    * revert SecureRandom and ignore the issue
---
 core/src/main/java/org/apache/hop/core/Const.java  |   2 +
 .../org/apache/hop/core/database/Database.java     |   2 +
 .../java/org/apache/hop/core/encryption/Encr.java  |   2 +
 .../org/apache/hop/core/logging/LoggingObject.java |   2 +
 .../apache/hop/core/plugins/PluginRegistry.java    |   8 ++
 .../main/java/org/apache/hop/laf/LafDelegate.java  |   2 +
 .../org/apache/hop/laf/OverlayPropertyHandler.java |   2 +
 .../apache/hop/core/util/SwingSvgImageUtil.java    |  10 +-
 .../apache/hop/encryption/HopCommandEncrypt.java   |   2 +
 .../hop/pipeline/debug/PipelineDebugMeta.java      |   2 +
 .../apache/hop/pipeline/transform/RunThread.java   |   2 +
 .../hop/workflow/actions/pgpencryptfiles/GPG.java  |   5 +-
 .../hop/workflow/actions/shell/ActionShell.java    |   2 +
 .../workflow/actions/zipfile/ActionZipFile.java    |   7 +-
 .../actions/zipfile/ActionZipFileAppendTest.java   | 114 +++++++++++++++++
 .../transforms/orabulkloader/OraBulkLoader.java    |   4 +
 .../bulkloader/SnowflakeBulkLoaderDialog.java      |   2 +
 .../vertica/bulkloader/VerticaBulkLoader.java      |   2 +
 .../HopPipelineMetaToBeamPipelineConverter.java    |   2 +
 .../java/org/apache/hop/beam/run/MainBeam.java     |   2 +
 .../src/main/java/org/apache/hop/git/HopDiff.java  |   2 +
 .../main/java/org/apache/hop/git/model/UIGit.java  |  18 +++
 .../hop/mail/metadata/MailServerConnection.java    |   3 +
 .../workflow/actions/getpop/MailConnection.java    |   3 +
 .../workflow/actions/mail/ActionMailDialog.java    |   5 +-
 .../project/ManageProjectsOptionPlugin.java        |   4 +
 .../org/apache/hop/projects/project/Project.java   |   2 +
 .../transforms/cassandrainput/CassandraInput.java  |   2 +
 .../cassandraoutput/CassandraOutput.java           |   2 +
 .../cassandraoutput/CassandraOutputDialog.java     |   4 +
 .../googleanalytics/BareBonesBrowserLaunch.java    |   3 +
 .../googleanalytics/GoogleAnalytics.java           |   6 +
 .../transforms/excelwriter/ods/OdsTableHelper.java |   3 +
 .../util/delimiters/DelimiterDetector.java         |   2 +
 .../hop/pipeline/transforms/ifnull/IfNull.java     |   2 +
 .../userdefinedjavaclass/TransformClassBase.java   |   2 +
 .../UserDefinedJavaClassDialog.java                |   2 +
 .../transforms/jdbcmetadata/JdbcMetadata.java      |   4 +
 .../transforms/randomvalue/RandomValue.java        |  15 ++-
 .../apache/hop/pipeline/transforms/rest/Rest.java  |   2 +
 .../hop/pipeline/transforms/csvinput/CsvInput.java |   2 +
 .../textfileoutput/TextFileOutputData.java         |   4 +
 .../transforms/webservices/WebServiceDialog.java   |   2 +
 .../getxmldata/LoopNodesImportProgressDialog.java  |   2 +
 .../XmlInputFieldsImportProgressDialog.java        |   2 +
 .../hop/pipeline/transforms/zipfile/ZipFile.java   |   9 +-
 .../transforms/zipfile/ZipFileAppendTest.java      | 140 +++++++++++++++++++++
 .../ui/core/widget/svg/SvgLabelListenerImpl.java   |   2 +
 .../ui/hopgui/HopWebServletContextListener.java    |   2 +
 .../org/apache/hop/ui/core/dialog/ErrorDialog.java |   4 +
 .../hop/ui/core/gui/GuiCompositeWidgets.java       |   2 +
 .../org/apache/hop/ui/core/widget/OsHelper.java    |   2 +
 .../org/apache/hop/ui/util/SwtSvgImageUtil.java    |  10 +-
 53 files changed, 424 insertions(+), 21 deletions(-)

diff --git a/core/src/main/java/org/apache/hop/core/Const.java 
b/core/src/main/java/org/apache/hop/core/Const.java
index e99cc8509c..e916818a48 100644
--- a/core/src/main/java/org/apache/hop/core/Const.java
+++ b/core/src/main/java/org/apache/hop/core/Const.java
@@ -2020,6 +2020,8 @@ public class Const {
       } else {
         BufferedReader br;
         try {
+          // Safe: resolving "hostname" through the PATH of the operator who 
started Hop is intended
+          @SuppressWarnings("java:S4036")
           Process pr = Runtime.getRuntime().exec("hostname");
           br = new BufferedReader(new InputStreamReader(pr.getInputStream()));
           String line;
diff --git a/core/src/main/java/org/apache/hop/core/database/Database.java 
b/core/src/main/java/org/apache/hop/core/database/Database.java
index d426640056..b03e6982d3 100644
--- a/core/src/main/java/org/apache/hop/core/database/Database.java
+++ b/core/src/main/java/org/apache/hop/core/database/Database.java
@@ -3527,6 +3527,8 @@ public class Database implements IVariables, 
ILoggingObject, AutoCloseable {
     return meta;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public RowMetaAndData getOneRow(String sql, IRowMeta param, Object[] data)
       throws HopDatabaseException {
     ResultSet rs = openQuery(sql, param, data);
diff --git a/core/src/main/java/org/apache/hop/core/encryption/Encr.java 
b/core/src/main/java/org/apache/hop/core/encryption/Encr.java
index 93eab02ec1..700d6553ad 100644
--- a/core/src/main/java/org/apache/hop/core/encryption/Encr.java
+++ b/core/src/main/java/org/apache/hop/core/encryption/Encr.java
@@ -184,6 +184,8 @@ public class Encr {
    *
    * @param args the password to encrypt
    */
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public static void main(String[] args) throws HopException {
     HopClientEnvironment.init();
     if (args.length != 2) {
diff --git a/core/src/main/java/org/apache/hop/core/logging/LoggingObject.java 
b/core/src/main/java/org/apache/hop/core/logging/LoggingObject.java
index a0ef7143e4..17be4b18cf 100644
--- a/core/src/main/java/org/apache/hop/core/logging/LoggingObject.java
+++ b/core/src/main/java/org/apache/hop/core/logging/LoggingObject.java
@@ -47,6 +47,8 @@ public class LoggingObject implements ILoggingObject {
     }
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public boolean equals(Object obj) {
     if (!(obj instanceof LoggingObject)) {
diff --git a/core/src/main/java/org/apache/hop/core/plugins/PluginRegistry.java 
b/core/src/main/java/org/apache/hop/core/plugins/PluginRegistry.java
index aaa781f558..839b90f702 100644
--- a/core/src/main/java/org/apache/hop/core/plugins/PluginRegistry.java
+++ b/core/src/main/java/org/apache/hop/core/plugins/PluginRegistry.java
@@ -109,6 +109,8 @@ public class PluginRegistry {
     }
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public void removePlugin(Class<? extends IPluginType> pluginType, IPlugin 
plugin) {
     lock.writeLock().lock();
     try {
@@ -417,6 +419,8 @@ public class PluginRegistry {
    * @return The instantiated class
    * @throws HopPluginException In case there was a class loading problem 
somehow
    */
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public <T> T loadClass(IPlugin plugin, Class<T> pluginClass) throws 
HopPluginException {
     if (plugin == null) {
       throw new HopPluginException(
@@ -876,6 +880,8 @@ public class PluginRegistry {
    * @throws HopPluginException In case there was a problem
    *     <p>getClassLoader();
    */
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public ClassLoader getClassLoader(IPlugin plugin) throws HopPluginException {
 
     if (plugin == null) {
@@ -1039,6 +1045,8 @@ public class PluginRegistry {
     return result;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public void reset() {
     lock.writeLock().lock();
     try {
diff --git a/core/src/main/java/org/apache/hop/laf/LafDelegate.java 
b/core/src/main/java/org/apache/hop/laf/LafDelegate.java
index 8cce147c14..1a8f8e621a 100644
--- a/core/src/main/java/org/apache/hop/laf/LafDelegate.java
+++ b/core/src/main/java/org/apache/hop/laf/LafDelegate.java
@@ -67,6 +67,8 @@ public class LafDelegate<E extends IHandler> {
     return h;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   private E loadHandler(Class<E> c) {
     E h = null;
     try {
diff --git a/core/src/main/java/org/apache/hop/laf/OverlayPropertyHandler.java 
b/core/src/main/java/org/apache/hop/laf/OverlayPropertyHandler.java
index b9ca28fade..84c99d354a 100644
--- a/core/src/main/java/org/apache/hop/laf/OverlayPropertyHandler.java
+++ b/core/src/main/java/org/apache/hop/laf/OverlayPropertyHandler.java
@@ -75,6 +75,8 @@ public class OverlayPropertyHandler implements 
IPropertyHandler {
     return getInstance().getProperty(key);
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public boolean loadProps(String filename) {
     try {
diff --git 
a/engine/src/main/java/org/apache/hop/core/util/SwingSvgImageUtil.java 
b/engine/src/main/java/org/apache/hop/core/util/SwingSvgImageUtil.java
index 7834bb4c2c..8252fd0297 100644
--- a/engine/src/main/java/org/apache/hop/core/util/SwingSvgImageUtil.java
+++ b/engine/src/main/java/org/apache/hop/core/util/SwingSvgImageUtil.java
@@ -39,15 +39,17 @@ import org.apache.hop.core.vfs.HopVfs;
  */
 public class SwingSvgImageUtil {
 
-  private static FileObject base;
+  private static FileObject base = resolveBase();
   private static final String NO_IMAGE = "ui/images/no_image.svg";
 
-  static {
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
+  private static FileObject resolveBase() {
     try {
-      base = 
HopVfs.getFileSystemManager().resolveFile(System.getProperty("user.dir"));
+      return 
HopVfs.getFileSystemManager().resolveFile(System.getProperty("user.dir"));
     } catch (FileSystemException e) {
       e.printStackTrace();
-      base = null;
+      return null;
     }
   }
 
diff --git 
a/engine/src/main/java/org/apache/hop/encryption/HopCommandEncrypt.java 
b/engine/src/main/java/org/apache/hop/encryption/HopCommandEncrypt.java
index e30f92f31b..cdaf9300f1 100644
--- a/engine/src/main/java/org/apache/hop/encryption/HopCommandEncrypt.java
+++ b/engine/src/main/java/org/apache/hop/encryption/HopCommandEncrypt.java
@@ -60,6 +60,8 @@ public class HopCommandEncrypt implements Runnable, 
IHopCommand {
     this.cmd = cmd;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public void run() {
     try {
diff --git 
a/engine/src/main/java/org/apache/hop/pipeline/debug/PipelineDebugMeta.java 
b/engine/src/main/java/org/apache/hop/pipeline/debug/PipelineDebugMeta.java
index ef4982edaa..5b88d5fd4a 100644
--- a/engine/src/main/java/org/apache/hop/pipeline/debug/PipelineDebugMeta.java
+++ b/engine/src/main/java/org/apache/hop/pipeline/debug/PipelineDebugMeta.java
@@ -55,6 +55,8 @@ public class PipelineDebugMeta {
     transformDebugMetaMap = new HashMap<>();
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public synchronized void addRowListenersToPipeline(final 
IPipelineEngine<PipelineMeta> pipeline) {
 
     // for every transform in the map, add a row listener...
diff --git 
a/engine/src/main/java/org/apache/hop/pipeline/transform/RunThread.java 
b/engine/src/main/java/org/apache/hop/pipeline/transform/RunThread.java
index d2ed0381e8..ab64a4a337 100644
--- a/engine/src/main/java/org/apache/hop/pipeline/transform/RunThread.java
+++ b/engine/src/main/java/org/apache/hop/pipeline/transform/RunThread.java
@@ -39,6 +39,8 @@ public class RunThread implements Runnable {
     this.log = transform.getLogChannel();
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public void run() {
     try {
diff --git 
a/plugins/actions/pgpfiles/src/main/java/org/apache/hop/workflow/actions/pgpencryptfiles/GPG.java
 
b/plugins/actions/pgpfiles/src/main/java/org/apache/hop/workflow/actions/pgpencryptfiles/GPG.java
index d698382133..db5b2096d5 100644
--- 
a/plugins/actions/pgpfiles/src/main/java/org/apache/hop/workflow/actions/pgpencryptfiles/GPG.java
+++ 
b/plugins/actions/pgpfiles/src/main/java/org/apache/hop/workflow/actions/pgpencryptfiles/GPG.java
@@ -24,6 +24,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.commons.vfs2.FileObject;
@@ -639,7 +640,9 @@ public class GPG {
     this.tmpFile = null;
 
     try {
-      this.tmpFile = File.createTempFile("GnuPG", null);
+      // Files.createTempFile creates an owner-only (0600) file on POSIX 
systems: it can hold
+      // the plain text to encrypt or sign and must not be readable by other 
OS users.
+      this.tmpFile = Files.createTempFile("GnuPG", null).toFile();
       if (log.isDebug()) {
         log.logDebug(BaseMessages.getString(PKG, "GPG.TempFileCreated", 
getTempFileName()));
       }
diff --git 
a/plugins/actions/shell/src/main/java/org/apache/hop/workflow/actions/shell/ActionShell.java
 
b/plugins/actions/shell/src/main/java/org/apache/hop/workflow/actions/shell/ActionShell.java
index 65021c75da..ec5e3ec8a3 100644
--- 
a/plugins/actions/shell/src/main/java/org/apache/hop/workflow/actions/shell/ActionShell.java
+++ 
b/plugins/actions/shell/src/main/java/org/apache/hop/workflow/actions/shell/ActionShell.java
@@ -603,6 +603,8 @@ public class ActionShell extends ActionBase implements 
ILegacyXml {
           // Now we have to make this file executable...
           // On Unix-like systems this is done using the command "/bin/chmod 
+x filename"
           //
+          // Safe: the shell action runs commands from the operator's own PATH 
by design
+          @SuppressWarnings("java:S4036")
           ProcessBuilder procBuilder = new ProcessBuilder("chmod", "+x", 
tempFilename);
           Process proc = procBuilder.start();
           // Eat/log stderr/stdout all messages in a different thread...
diff --git 
a/plugins/actions/zipfile/src/main/java/org/apache/hop/workflow/actions/zipfile/ActionZipFile.java
 
b/plugins/actions/zipfile/src/main/java/org/apache/hop/workflow/actions/zipfile/ActionZipFile.java
index e3d7f1fb3e..eb57d8739b 100644
--- 
a/plugins/actions/zipfile/src/main/java/org/apache/hop/workflow/actions/zipfile/ActionZipFile.java
+++ 
b/plugins/actions/zipfile/src/main/java/org/apache/hop/workflow/actions/zipfile/ActionZipFile.java
@@ -363,7 +363,12 @@ public class ActionZipFile extends ActionBase implements 
Cloneable, IAction {
               // the zip file exists and user want to append
               // get a temp file
               fileZip = getFile(localrealZipfilename);
-              tempFile = File.createTempFile(fileZip.getName(), null);
+              // Create the temporary file next to the zip file, not in the 
shared system temp
+              // folder: the rename below then stays on the same file system 
and no other user
+              // can claim the name.
+              tempFile =
+                  File.createTempFile(
+                      fileZip.getName(), null, 
fileZip.getAbsoluteFile().getParentFile());
 
               // delete it, otherwise we cannot rename existing zip to it.
               if (!tempFile.delete()) {
diff --git 
a/plugins/actions/zipfile/src/test/java/org/apache/hop/workflow/actions/zipfile/ActionZipFileAppendTest.java
 
b/plugins/actions/zipfile/src/test/java/org/apache/hop/workflow/actions/zipfile/ActionZipFileAppendTest.java
new file mode 100644
index 0000000000..a27742812b
--- /dev/null
+++ 
b/plugins/actions/zipfile/src/test/java/org/apache/hop/workflow/actions/zipfile/ActionZipFileAppendTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.hop.workflow.actions.zipfile;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+import org.apache.hop.core.HopClientEnvironment;
+import org.apache.hop.core.Result;
+import org.apache.hop.core.logging.HopLogStore;
+import org.apache.hop.core.logging.LogLevel;
+import org.apache.hop.workflow.WorkflowMeta;
+import org.apache.hop.workflow.engines.local.LocalWorkflowEngine;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+/** Appending to an existing zip file must not go through the shared system 
temp folder. */
+class ActionZipFileAppendTest {
+
+  @TempDir Path tempDir;
+
+  @BeforeAll
+  static void init() throws Exception {
+    HopClientEnvironment.init();
+    HopLogStore.init();
+  }
+
+  @Test
+  void appendKeepsExistingEntriesAndUsesTheZipFolderForTheTemporaryFile() 
throws Exception {
+    Path sourceDir = Files.createDirectories(tempDir.resolve("source"));
+    Files.writeString(sourceDir.resolve("new.txt"), "new", 
StandardCharsets.UTF_8);
+    Path zipDir = Files.createDirectories(tempDir.resolve("archive"));
+    Path zip = zipDir.resolve("archive.zip");
+    writeZip(zip, "old.txt", "old");
+
+    ActionZipFile action = new ActionZipFile();
+    action.setParentWorkflow(new LocalWorkflowEngine(new WorkflowMeta()));
+    action.setParentWorkflowMeta(mock(WorkflowMeta.class));
+    action.setLogLevel(LogLevel.ERROR);
+    action.setSourceDirectory(sourceDir.toString());
+    action.setWildCard(".*\\.txt");
+    action.setZipFilename(zip.toString());
+    action.setIfZipFileExists(1); // append
+    action.setAfterZip(0); // leave the source files alone
+
+    List<File> tempFolders = new ArrayList<>();
+    Result result;
+    try (MockedStatic<File> files = Mockito.mockStatic(File.class, 
Mockito.CALLS_REAL_METHODS)) {
+      files
+          .when(() -> File.createTempFile(anyString(), any(), any()))
+          .thenAnswer(
+              invocation -> {
+                tempFolders.add(invocation.getArgument(2));
+                return invocation.callRealMethod();
+              });
+      result = action.execute(new Result(), 0);
+    }
+
+    assertTrue(result.isResult(), "zipping should succeed");
+    assertEquals(0, result.getNrErrors());
+    assertEquals(Set.of("old.txt", "new.txt"), entries(zip));
+    assertEquals(List.of(zipDir.toFile()), tempFolders, "temporary file 
folder");
+    assertEquals(
+        List.of(zip), Files.list(zipDir).toList(), "no temporary file should 
be left behind");
+  }
+
+  static void writeZip(Path zip, String entry, String content) throws 
Exception {
+    try (ZipOutputStream out = new 
ZipOutputStream(Files.newOutputStream(zip))) {
+      out.putNextEntry(new ZipEntry(entry));
+      out.write(content.getBytes(StandardCharsets.UTF_8));
+      out.closeEntry();
+    }
+  }
+
+  static Set<String> entries(Path zip) throws Exception {
+    Set<String> names = new TreeSet<>();
+    try (ZipFile zipFile = new ZipFile(zip.toFile())) {
+      zipFile.stream().forEach(entry -> names.add(entry.getName()));
+    }
+    return names;
+  }
+}
diff --git 
a/plugins/databases/oracle/src/main/java/org/apache/hop/pipeline/transforms/orabulkloader/OraBulkLoader.java
 
b/plugins/databases/oracle/src/main/java/org/apache/hop/pipeline/transforms/orabulkloader/OraBulkLoader.java
index 2e418bebec..0b5b88f1b6 100644
--- 
a/plugins/databases/oracle/src/main/java/org/apache/hop/pipeline/transforms/orabulkloader/OraBulkLoader.java
+++ 
b/plugins/databases/oracle/src/main/java/org/apache/hop/pipeline/transforms/orabulkloader/OraBulkLoader.java
@@ -90,6 +90,8 @@ public class OraBulkLoader extends 
BaseTransform<OraBulkLoaderMeta, OraBulkLoade
       this.type = type + ">";
     }
 
+    // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+    @SuppressWarnings("java:S4507")
     @Override
     public void run() {
       try {
@@ -622,6 +624,8 @@ public class OraBulkLoader extends 
BaseTransform<OraBulkLoaderMeta, OraBulkLoade
     return false;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public void dispose() {
 
diff --git 
a/plugins/databases/snowflake/src/main/java/org/apache/hop/pipeline/transforms/snowflake/bulkloader/SnowflakeBulkLoaderDialog.java
 
b/plugins/databases/snowflake/src/main/java/org/apache/hop/pipeline/transforms/snowflake/bulkloader/SnowflakeBulkLoaderDialog.java
index 91879c1a5a..e533aa3b94 100644
--- 
a/plugins/databases/snowflake/src/main/java/org/apache/hop/pipeline/transforms/snowflake/bulkloader/SnowflakeBulkLoaderDialog.java
+++ 
b/plugins/databases/snowflake/src/main/java/org/apache/hop/pipeline/transforms/snowflake/bulkloader/SnowflakeBulkLoaderDialog.java
@@ -1688,6 +1688,8 @@ public class SnowflakeBulkLoaderDialog extends 
BaseTransformDialog {
 
   // Generate code for create table...
   // Conversions done by Database
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   private void create() {
     DatabaseMeta databaseMeta = 
pipelineMeta.findDatabase(wConnection.getText(), variables);
 
diff --git 
a/plugins/databases/vertica/src/main/java/org/apache/hop/pipeline/transforms/vertica/bulkloader/VerticaBulkLoader.java
 
b/plugins/databases/vertica/src/main/java/org/apache/hop/pipeline/transforms/vertica/bulkloader/VerticaBulkLoader.java
index 42f9fc1226..7cab5d5cea 100644
--- 
a/plugins/databases/vertica/src/main/java/org/apache/hop/pipeline/transforms/vertica/bulkloader/VerticaBulkLoader.java
+++ 
b/plugins/databases/vertica/src/main/java/org/apache/hop/pipeline/transforms/vertica/bulkloader/VerticaBulkLoader.java
@@ -75,6 +75,8 @@ public class VerticaBulkLoader extends 
BaseTransform<VerticaBulkLoaderMeta, Vert
     super(transformMeta, meta, data, copyNr, pipelineMeta, pipeline);
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public boolean processRow() throws HopException {
     Object[] r = getRow(); // this also waits for a previous transform to be
diff --git 
a/plugins/engines/beam/src/main/java/org/apache/hop/beam/pipeline/HopPipelineMetaToBeamPipelineConverter.java
 
b/plugins/engines/beam/src/main/java/org/apache/hop/beam/pipeline/HopPipelineMetaToBeamPipelineConverter.java
index 4e8b2a43d4..be090e9f2b 100644
--- 
a/plugins/engines/beam/src/main/java/org/apache/hop/beam/pipeline/HopPipelineMetaToBeamPipelineConverter.java
+++ 
b/plugins/engines/beam/src/main/java/org/apache/hop/beam/pipeline/HopPipelineMetaToBeamPipelineConverter.java
@@ -320,6 +320,8 @@ public class HopPipelineMetaToBeamPipelineConverter {
     pipelineOptions.setRunner(runnerClass);
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public Pipeline createPipeline() throws Exception {
     try {
       ILogChannel log = LogChannel.GENERAL;
diff --git 
a/plugins/engines/beam/src/main/java/org/apache/hop/beam/run/MainBeam.java 
b/plugins/engines/beam/src/main/java/org/apache/hop/beam/run/MainBeam.java
index f4e48b5a46..0db75c0061 100644
--- a/plugins/engines/beam/src/main/java/org/apache/hop/beam/run/MainBeam.java
+++ b/plugins/engines/beam/src/main/java/org/apache/hop/beam/run/MainBeam.java
@@ -44,6 +44,8 @@ import org.apache.hop.pipeline.engine.PipelineEngineFactory;
 
 public class MainBeam {
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public static void main(String[] args) {
     try {
       System.out.println(">>>>>> Initializing Hop");
diff --git a/plugins/misc/git/src/main/java/org/apache/hop/git/HopDiff.java 
b/plugins/misc/git/src/main/java/org/apache/hop/git/HopDiff.java
index 97bf60361f..abbddb6f7f 100644
--- a/plugins/misc/git/src/main/java/org/apache/hop/git/HopDiff.java
+++ b/plugins/misc/git/src/main/java/org/apache/hop/git/HopDiff.java
@@ -168,6 +168,8 @@ public class HopDiff {
     return identities;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public static PipelineMeta compareTransforms(
       PipelineMeta pipelineMeta1,
       PipelineMeta pipelineMeta2,
diff --git a/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java 
b/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java
index 1bde3bf615..dd3b3d8318 100644
--- a/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java
+++ b/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java
@@ -198,6 +198,8 @@ public class UIGit extends VCS {
     }
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public String getCommitId(String revstr) {
     ObjectId id = null;
     try {
@@ -261,6 +263,8 @@ public class UIGit extends VCS {
    * @param mode
    * @return
    */
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   private List<String> getBranches(ListMode mode) {
     try {
       return git.branchList().setListMode(mode).call().stream()
@@ -563,6 +567,8 @@ public class UIGit extends VCS {
     return getUnstagedFiles(null);
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public List<UIFile> getUnstagedFiles(String path) {
     List<UIFile> files = new ArrayList<>();
     Status status = null;
@@ -589,6 +595,8 @@ public class UIGit extends VCS {
     return files;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public List<UIFile> getStagedFiles() {
     List<UIFile> files = new ArrayList<>();
     Status status = null;
@@ -605,6 +613,8 @@ public class UIGit extends VCS {
     return files;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public List<UIFile> getStagedFiles(String oldCommitId, String newCommitId) {
     List<UIFile> files = new ArrayList<>();
     try {
@@ -1604,6 +1614,8 @@ public class UIGit extends VCS {
     return list.toString();
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   private boolean hasUncommittedChanges() {
     try {
       return git.status().call().hasUncommittedChanges();
@@ -1691,6 +1703,8 @@ public class UIGit extends VCS {
     }
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public boolean isClean() {
     try {
       return git.status().call().isClean();
@@ -1700,6 +1714,8 @@ public class UIGit extends VCS {
     }
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public List<String> getTags() {
     try {
       return git.tagList().call().stream()
@@ -1766,6 +1782,8 @@ public class UIGit extends VCS {
     credentialsProvider = new UsernamePasswordCredentialsProvider(username, 
password);
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public RevCommit resolve(String commitId) {
     ObjectId id = null;
     try {
diff --git 
a/plugins/misc/mail/src/main/java/org/apache/hop/mail/metadata/MailServerConnection.java
 
b/plugins/misc/mail/src/main/java/org/apache/hop/mail/metadata/MailServerConnection.java
index 8af71a3aa6..c2070dce4c 100644
--- 
a/plugins/misc/mail/src/main/java/org/apache/hop/mail/metadata/MailServerConnection.java
+++ 
b/plugins/misc/mail/src/main/java/org/apache/hop/mail/metadata/MailServerConnection.java
@@ -1063,6 +1063,9 @@ public class MailServerConnection extends HopMetadataBase 
implements IHopMetadat
       // Do no overwrite existing file
       String targetFileName;
       if (filename == null) {
+        // Safe: the temporary file only supplies a unique name, the 
attachment itself is written
+        // to the target folder chosen by the user
+        @SuppressWarnings("java:S5443")
         File f = File.createTempFile("xx", ".out");
         f.deleteOnExit(); // Clean up file
         filename = f.getName();
diff --git 
a/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/getpop/MailConnection.java
 
b/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/getpop/MailConnection.java
index 9c0b667fb3..23590f4b95 100644
--- 
a/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/getpop/MailConnection.java
+++ 
b/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/getpop/MailConnection.java
@@ -863,6 +863,9 @@ public class MailConnection {
       // Do no overwrite existing file
       String targetFileName;
       if (filename == null) {
+        // Safe: the temporary file only supplies a unique name, the 
attachment itself is written
+        // to the target folder chosen by the user
+        @SuppressWarnings("java:S5443")
         File f = File.createTempFile("xx", ".out");
         f.deleteOnExit(); // Clean up file
         filename = f.getName();
diff --git 
a/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/mail/ActionMailDialog.java
 
b/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/mail/ActionMailDialog.java
index 191a9564b5..85fbf64b97 100644
--- 
a/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/mail/ActionMailDialog.java
+++ 
b/plugins/misc/mail/src/main/java/org/apache/hop/mail/workflow/actions/mail/ActionMailDialog.java
@@ -1204,8 +1204,9 @@ public class ActionMailDialog extends ActionDialog {
                   IMAGES_FILE_TYPES,
                   true);
           if (filename != null) {
-            // Created once per image the user picks, reuse would gain us 
nothing
-            @SuppressWarnings("java:S2119")
+            // Created once per image the user picks, reuse would gain us 
nothing.
+            // Safe: a MIME Content-ID only has to be unique within the 
message, not unpredictable
+            @SuppressWarnings({"java:S2119", "java:S2245"})
             Random random = new Random();
             wContentID.setText(Long.toString(Math.abs(random.nextLong()), 32));
           }
diff --git 
a/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/ManageProjectsOptionPlugin.java
 
b/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/ManageProjectsOptionPlugin.java
index 3c35a67d54..f4b4c9527d 100644
--- 
a/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/ManageProjectsOptionPlugin.java
+++ 
b/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/ManageProjectsOptionPlugin.java
@@ -469,6 +469,8 @@ public class ManageProjectsOptionPlugin implements 
IConfigOptions {
     log.logBasic("Metadata was exported successfully.");
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public void listActionTypes(
       ILogChannel log,
       ProjectsConfig config,
@@ -498,6 +500,8 @@ public class ManageProjectsOptionPlugin implements 
IConfigOptions {
     }
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public void listTransformTypes(
       ILogChannel log,
       ProjectsConfig config,
diff --git 
a/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/Project.java
 
b/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/Project.java
index 87a3bbbaeb..f06bb1b948 100644
--- 
a/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/Project.java
+++ 
b/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/Project.java
@@ -480,6 +480,8 @@ public class Project extends ConfigFile implements 
IConfigFile {
    * @throws IOException
    * @throws HopFileException
    */
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public List<String> getTransformTypes(IVariables variables) throws 
IOException, HopFileException {
     // build a map of all pipelines and transforms in the project.
     buildPipelineMap(variables);
diff --git 
a/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandrainput/CassandraInput.java
 
b/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandrainput/CassandraInput.java
index 4e92fd7265..f2daf53e4d 100644
--- 
a/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandrainput/CassandraInput.java
+++ 
b/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandrainput/CassandraInput.java
@@ -269,6 +269,8 @@ public class CassandraInput extends 
BaseTransform<CassandraInputMeta, CassandraI
     super.setStopped(stopped);
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public void dispose() {
     try {
diff --git 
a/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandraoutput/CassandraOutput.java
 
b/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandraoutput/CassandraOutput.java
index 2b4862f41d..7b0d261de7 100644
--- 
a/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandraoutput/CassandraOutput.java
+++ 
b/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandraoutput/CassandraOutput.java
@@ -566,6 +566,8 @@ public class CassandraOutput extends 
BaseTransform<CassandraOutputMeta, Cassandr
     }
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public void dispose() {
     try {
diff --git 
a/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandraoutput/CassandraOutputDialog.java
 
b/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandraoutput/CassandraOutputDialog.java
index e3c6f9298c..02e27ce45a 100644
--- 
a/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandraoutput/CassandraOutputDialog.java
+++ 
b/plugins/tech/cassandra/src/main/java/org/apache/hop/pipeline/transforms/cassandraoutput/CassandraOutputDialog.java
@@ -558,6 +558,8 @@ public class CassandraOutputDialog extends 
BaseTransformDialog {
     return transformName;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   protected void setupTablesCombo() {
     DriverConnection conn = null;
     Keyspace kSpace = null;
@@ -764,6 +766,8 @@ public class CassandraOutputDialog extends 
BaseTransformDialog {
     dispose();
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   protected void popupSchemaInfo() {
     DriverConnection conn = null;
     Keyspace kSpace = null;
diff --git 
a/plugins/tech/google/src/main/java/org/apache/hop/pipeline/transforms/googleanalytics/BareBonesBrowserLaunch.java
 
b/plugins/tech/google/src/main/java/org/apache/hop/pipeline/transforms/googleanalytics/BareBonesBrowserLaunch.java
index 3789337587..4eb056bcda 100644
--- 
a/plugins/tech/google/src/main/java/org/apache/hop/pipeline/transforms/googleanalytics/BareBonesBrowserLaunch.java
+++ 
b/plugins/tech/google/src/main/java/org/apache/hop/pipeline/transforms/googleanalytics/BareBonesBrowserLaunch.java
@@ -38,6 +38,9 @@ public class BareBonesBrowserLaunch {
    *
    * @param url A web address (URL) of a web page (ex: 
"http://www.google.com/";)
    */
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client, and the
+  // browser is looked up on the PATH of the desktop user who is signing in, 
which is intended
+  @SuppressWarnings({"java:S4507", "java:S4036"})
   public static void openURL(String url) {
     try { // attempt to use Desktop library from JDK 1.6+
       Class<?> d = Class.forName("java.awt.Desktop");
diff --git 
a/plugins/tech/google/src/main/java/org/apache/hop/pipeline/transforms/googleanalytics/GoogleAnalytics.java
 
b/plugins/tech/google/src/main/java/org/apache/hop/pipeline/transforms/googleanalytics/GoogleAnalytics.java
index b220982015..dd3403b1c7 100644
--- 
a/plugins/tech/google/src/main/java/org/apache/hop/pipeline/transforms/googleanalytics/GoogleAnalytics.java
+++ 
b/plugins/tech/google/src/main/java/org/apache/hop/pipeline/transforms/googleanalytics/GoogleAnalytics.java
@@ -72,6 +72,8 @@ public class GoogleAnalytics extends 
BaseTransform<GoogleAnalyticsMeta, GoogleAn
     super(transformMeta, meta, data, copyNr, pipelineMeta, pipeline);
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public boolean init() {
 
@@ -145,6 +147,8 @@ public class GoogleAnalytics extends 
BaseTransform<GoogleAnalyticsMeta, GoogleAn
     return false;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   private void readResponse() {
     List<DimensionHeader> dimensionHeaders;
     RunReportResponse response = analyticsData.runReport(getRequest());
@@ -225,6 +229,8 @@ public class GoogleAnalytics extends 
BaseTransform<GoogleAnalyticsMeta, GoogleAn
     return super.subStatuses();
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public void dispose() {
     try {
diff --git 
a/plugins/transforms/excel/src/main/java/org/apache/hop/pipeline/transforms/excelwriter/ods/OdsTableHelper.java
 
b/plugins/transforms/excel/src/main/java/org/apache/hop/pipeline/transforms/excelwriter/ods/OdsTableHelper.java
index df0560c48a..2c7472733a 100644
--- 
a/plugins/transforms/excel/src/main/java/org/apache/hop/pipeline/transforms/excelwriter/ods/OdsTableHelper.java
+++ 
b/plugins/transforms/excel/src/main/java/org/apache/hop/pipeline/transforms/excelwriter/ods/OdsTableHelper.java
@@ -141,6 +141,9 @@ final class OdsTableHelper {
     if (Utils.isEmpty(password)) {
       return;
     }
+    // Safe: table protection is an editing lock honoured by the office 
application, not a
+    // security control, and SHA-1 is the default ODF digest for its 
protection key
+    @SuppressWarnings("java:S4790")
     MessageDigest digest = MessageDigest.getInstance("SHA-1");
     digest.update(password.getBytes(StandardCharsets.UTF_8));
     
element.setTableProtectionKeyAttribute(Base64.getEncoder().encodeToString(digest.digest()));
diff --git 
a/plugins/transforms/filemetadata/src/main/java/org/apache/hop/pipeline/transforms/filemetadata/util/delimiters/DelimiterDetector.java
 
b/plugins/transforms/filemetadata/src/main/java/org/apache/hop/pipeline/transforms/filemetadata/util/delimiters/DelimiterDetector.java
index 9ec366e361..7c2df916b7 100644
--- 
a/plugins/transforms/filemetadata/src/main/java/org/apache/hop/pipeline/transforms/filemetadata/util/delimiters/DelimiterDetector.java
+++ 
b/plugins/transforms/filemetadata/src/main/java/org/apache/hop/pipeline/transforms/filemetadata/util/delimiters/DelimiterDetector.java
@@ -212,6 +212,8 @@ public class DelimiterDetector {
     this.maxBadFooterLines = maxBadFooterLines;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public DetectionResult detectDelimiters() throws IOException {
 
     // potential configuration candidates with enclosure
diff --git 
a/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNull.java
 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNull.java
index f6af2759b8..800811ecc5 100644
--- 
a/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNull.java
+++ 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNull.java
@@ -45,6 +45,8 @@ public class IfNull extends BaseTransform<IfNullMeta, 
IfNullData> {
     super(transformMeta, meta, data, copyNr, pipelineMeta, pipeline);
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public boolean processRow() throws HopException {
 
diff --git 
a/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/TransformClassBase.java
 
b/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/TransformClassBase.java
index a50cdd30de..3dbcae2b93 100644
--- 
a/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/TransformClassBase.java
+++ 
b/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/TransformClassBase.java
@@ -57,6 +57,8 @@ public abstract class TransformClassBase {
   protected UserDefinedJavaClassMeta meta;
   protected UserDefinedJavaClassData data;
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public TransformClassBase(
       UserDefinedJavaClass parent, UserDefinedJavaClassMeta meta, 
UserDefinedJavaClassData data)
       throws HopTransformException {
diff --git 
a/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/UserDefinedJavaClassDialog.java
 
b/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/UserDefinedJavaClassDialog.java
index b698329d37..5f168d4295 100644
--- 
a/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/UserDefinedJavaClassDialog.java
+++ 
b/plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/userdefinedjavaclass/UserDefinedJavaClassDialog.java
@@ -1026,6 +1026,8 @@ public class UserDefinedJavaClassDialog extends 
BaseTransformDialog {
   }
 
   /** Copy information from the meta-data input to the dialog fields. */
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public void getData() {
     int i = 0;
     for (FieldInfo fi : input.getFields()) {
diff --git 
a/plugins/transforms/jdbc-metadata/src/main/java/org/apache/hop/pipeline/transforms/jdbcmetadata/JdbcMetadata.java
 
b/plugins/transforms/jdbc-metadata/src/main/java/org/apache/hop/pipeline/transforms/jdbcmetadata/JdbcMetadata.java
index 440947656c..7e93e1c784 100644
--- 
a/plugins/transforms/jdbc-metadata/src/main/java/org/apache/hop/pipeline/transforms/jdbcmetadata/JdbcMetadata.java
+++ 
b/plugins/transforms/jdbc-metadata/src/main/java/org/apache/hop/pipeline/transforms/jdbcmetadata/JdbcMetadata.java
@@ -179,6 +179,8 @@ public class JdbcMetadata extends 
BaseTransform<JdbcMetadataMeta, JdbcMetadataDa
     }
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public boolean init() {
     boolean result = true;
@@ -265,6 +267,8 @@ public class JdbcMetadata extends 
BaseTransform<JdbcMetadataMeta, JdbcMetadataDa
     return outputRow;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public boolean processRow() throws HopException {
 
diff --git 
a/plugins/transforms/randomvalue/src/main/java/org/apache/hop/pipeline/transforms/randomvalue/RandomValue.java
 
b/plugins/transforms/randomvalue/src/main/java/org/apache/hop/pipeline/transforms/randomvalue/RandomValue.java
index 4d77dfffb4..83557e12ce 100644
--- 
a/plugins/transforms/randomvalue/src/main/java/org/apache/hop/pipeline/transforms/randomvalue/RandomValue.java
+++ 
b/plugins/transforms/randomvalue/src/main/java/org/apache/hop/pipeline/transforms/randomvalue/RandomValue.java
@@ -277,12 +277,15 @@ public class RandomValue extends 
BaseTransform<RandomValueMeta, RandomValueData>
       }
     }
     if (random) {
-      if (StringUtils.isEmpty(meta.getSeed())) {
-        data.randomGenerator = new Random();
-      } else {
-        long seed = Const.toLong(resolve(meta.getSeed()), 0);
-        data.randomGenerator = new Random(seed);
-      }
+      // Generates test data, not security tokens (use the UUID or HMAC types 
for those).
+      // SecureRandom is avoided on purpose: it is called per row and 
NativePRNG serializes all
+      // transform copies on one JVM-wide lock. Each copy gets its own 
uncontended Random.
+      @SuppressWarnings("java:S2245")
+      Random generator =
+          StringUtils.isEmpty(meta.getSeed())
+              ? new Random()
+              : new Random(Const.toLong(resolve(meta.getSeed()), 0));
+      data.randomGenerator = generator;
     }
     if (genHmacMD5) {
       try {
diff --git 
a/plugins/transforms/rest/src/main/java/org/apache/hop/pipeline/transforms/rest/Rest.java
 
b/plugins/transforms/rest/src/main/java/org/apache/hop/pipeline/transforms/rest/Rest.java
index ab51965bfc..ac75b8d49b 100644
--- 
a/plugins/transforms/rest/src/main/java/org/apache/hop/pipeline/transforms/rest/Rest.java
+++ 
b/plugins/transforms/rest/src/main/java/org/apache/hop/pipeline/transforms/rest/Rest.java
@@ -1616,6 +1616,8 @@ public class Rest extends BaseTransform<RestMeta, 
RestData> {
     long expDelay = delay * (1L << attempt);
     long capped = Math.min(expDelay, maxDelay);
 
+    // Safe: retry jitter only spreads out load, it does not need to be 
unpredictable
+    @SuppressWarnings("java:S2245")
     long jitter = ThreadLocalRandom.current().nextLong(delay);
     return capped / 2 + jitter;
   }
diff --git 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/csvinput/CsvInput.java
 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/csvinput/CsvInput.java
index cc3072abe0..bade434e06 100644
--- 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/csvinput/CsvInput.java
+++ 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/csvinput/CsvInput.java
@@ -565,6 +565,8 @@ public class CsvInput extends BaseTransform<CsvInputMeta, 
CsvInputData> {
    * <p>So, we DON'T skip line only if the previous char is new line indicator 
AND we are not
    * between '\r\n'.
    */
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   private boolean needToSkipRow() {
     try {
       // first we move pointer to the last byte of the previous transform
diff --git 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/textfileoutput/TextFileOutputData.java
 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/textfileoutput/TextFileOutputData.java
index 22b06ea103..057b84381d 100644
--- 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/textfileoutput/TextFileOutputData.java
+++ 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/textfileoutput/TextFileOutputData.java
@@ -205,6 +205,8 @@ public class TextFileOutputData extends BaseTransformData 
implements ITransformD
       }
     }
 
+    // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+    @SuppressWarnings("java:S4507")
     @Override
     public void flushOpenFiles(boolean closeAfterFlush) throws IOException {
       for (FileStream outputStream : streamsList) {
@@ -397,6 +399,8 @@ public class TextFileOutputData extends BaseTransformData 
implements ITransformD
       }
     }
 
+    // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+    @SuppressWarnings("java:S4507")
     @Override
     public void flushOpenFiles(boolean closeAfterFlush) {
       for (FileStreamsCollectionEntry collectionEntry : indexMap.values()) {
diff --git 
a/plugins/transforms/webservices/src/main/java/org/apache/hop/pipeline/transforms/webservices/WebServiceDialog.java
 
b/plugins/transforms/webservices/src/main/java/org/apache/hop/pipeline/transforms/webservices/WebServiceDialog.java
index 0a17d8962a..686583f9db 100644
--- 
a/plugins/transforms/webservices/src/main/java/org/apache/hop/pipeline/transforms/webservices/WebServiceDialog.java
+++ 
b/plugins/transforms/webservices/src/main/java/org/apache/hop/pipeline/transforms/webservices/WebServiceDialog.java
@@ -783,6 +783,8 @@ public class WebServiceDialog extends BaseTransformDialog {
     meta = transformMeta;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public String open() {
     createShell(BaseMessages.getString(PKG, "WebServiceDialog.DialogTitle"));
diff --git 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/LoopNodesImportProgressDialog.java
 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/LoopNodesImportProgressDialog.java
index 1f5c00a76f..377d6ee48d 100644
--- 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/LoopNodesImportProgressDialog.java
+++ 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/LoopNodesImportProgressDialog.java
@@ -90,6 +90,8 @@ public class LoopNodesImportProgressDialog {
     this.nr = 0;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public String[] open(IVariables variables) {
     IRunnableWithProgress op =
         monitor -> {
diff --git 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/XmlInputFieldsImportProgressDialog.java
 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/XmlInputFieldsImportProgressDialog.java
index 7b761e27a6..fc033613c2 100644
--- 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/XmlInputFieldsImportProgressDialog.java
+++ 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/getxmldata/XmlInputFieldsImportProgressDialog.java
@@ -110,6 +110,8 @@ public class XmlInputFieldsImportProgressDialog {
     this.fields = null;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public RowMetaAndData[] open(IVariables variables) {
     IRunnableWithProgress op =
         monitor -> {
diff --git 
a/plugins/transforms/zipfile/src/main/java/org/apache/hop/pipeline/transforms/zipfile/ZipFile.java
 
b/plugins/transforms/zipfile/src/main/java/org/apache/hop/pipeline/transforms/zipfile/ZipFile.java
index 0b4387ff4a..e926511e9e 100644
--- 
a/plugins/transforms/zipfile/src/main/java/org/apache/hop/pipeline/transforms/zipfile/ZipFile.java
+++ 
b/plugins/transforms/zipfile/src/main/java/org/apache/hop/pipeline/transforms/zipfile/ZipFile.java
@@ -340,8 +340,8 @@ public class ZipFile extends BaseTransform<ZipFileMeta, 
ZipFileData> {
     try {
       URI uri = new URI(filename);
       return new File(uri);
-    } catch (URISyntaxException ex) {
-      // Ignore errors
+    } catch (URISyntaxException | IllegalArgumentException ex) {
+      // Not a file:// URI but a plain path such as /tmp/archive.zip or 
C:\archive.zip
     }
     return new File(filename);
   }
@@ -372,7 +372,10 @@ public class ZipFile extends BaseTransform<ZipFileMeta, 
ZipFileData> {
         // and we weed to update entries
         // Let's create a temp file
         File fileZip = getFile(localrealZipfilename);
-        tempFile = File.createTempFile(fileZip.getName(), null);
+        // Create the temporary file next to the zip file, not in the shared 
system temp folder: the
+        // rename below then stays on the same file system and no other user 
can claim the name.
+        tempFile =
+            File.createTempFile(fileZip.getName(), null, 
fileZip.getAbsoluteFile().getParentFile());
         // delete it, otherwise we cannot rename existing zip to it.
         tempFile.delete();
 
diff --git 
a/plugins/transforms/zipfile/src/test/java/org/apache/hop/pipeline/transforms/zipfile/ZipFileAppendTest.java
 
b/plugins/transforms/zipfile/src/test/java/org/apache/hop/pipeline/transforms/zipfile/ZipFileAppendTest.java
new file mode 100644
index 0000000000..34863e1b27
--- /dev/null
+++ 
b/plugins/transforms/zipfile/src/test/java/org/apache/hop/pipeline/transforms/zipfile/ZipFileAppendTest.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.hop.pipeline.transforms.zipfile;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import org.apache.hop.core.BlockingRowSet;
+import org.apache.hop.core.HopEnvironment;
+import org.apache.hop.core.logging.ILoggingObject;
+import org.apache.hop.core.row.RowMeta;
+import org.apache.hop.core.row.value.ValueMetaString;
+import org.apache.hop.junit.rules.RestoreHopEngineEnvironmentExtension;
+import org.apache.hop.pipeline.PipelineTestingUtil;
+import org.apache.hop.pipeline.transforms.mock.TransformMockHelper;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+/** Updating an existing zip file must not go through the shared system temp 
folder. */
+class ZipFileAppendTest {
+
+  @RegisterExtension
+  static RestoreHopEngineEnvironmentExtension env = new 
RestoreHopEngineEnvironmentExtension();
+
+  @TempDir Path tempDir;
+
+  private TransformMockHelper<ZipFileMeta, ZipFileData> helper;
+
+  @BeforeAll
+  static void initHop() throws Exception {
+    HopEnvironment.init();
+  }
+
+  @BeforeEach
+  void setUp() {
+    helper = new TransformMockHelper<>("ZipFileAppendTest", ZipFileMeta.class, 
ZipFileData.class);
+    when(helper.logChannelFactory.create(any(), any(ILoggingObject.class)))
+        .thenReturn(helper.iLogChannel);
+    
when(helper.logChannelFactory.create(any())).thenReturn(helper.iLogChannel);
+    when(helper.pipeline.isRunning()).thenReturn(true);
+  }
+
+  @AfterEach
+  void tearDown() {
+    helper.cleanUp();
+  }
+
+  @Test
+  void updateKeepsExistingEntriesAndUsesTheZipFolderForTheTemporaryFile() 
throws Exception {
+    Path source = 
Files.createDirectories(tempDir.resolve("source")).resolve("new.txt");
+    Files.writeString(source, "new", StandardCharsets.UTF_8);
+    Path zipDir = Files.createDirectories(tempDir.resolve("archive"));
+    Path zip = zipDir.resolve("archive.zip");
+    writeZip(zip, "old.txt", "old");
+
+    ZipFileMeta meta = new ZipFileMeta();
+    meta.setDefault();
+    meta.setSourceFilenameField("source");
+    meta.setTargetFilenameField("zip");
+    meta.setOverwriteZipEntry(true); // update the existing zip instead of 
replacing it
+
+    ZipFile transform =
+        new ZipFile(
+            helper.transformMeta, meta, new ZipFileData(), 0, 
helper.pipelineMeta, helper.pipeline);
+    RowMeta rowMeta = new RowMeta();
+    rowMeta.addValueMeta(new ValueMetaString("source"));
+    rowMeta.addValueMeta(new ValueMetaString("zip"));
+    BlockingRowSet input = new BlockingRowSet(2);
+    input.putRow(rowMeta, new Object[] {source.toUri().toString(), 
zip.toUri().toString()});
+    input.setDone();
+    transform.setInputRowSets(new ArrayList<>(List.of(input)));
+
+    List<File> tempFolders = new ArrayList<>();
+    try (MockedStatic<File> files = Mockito.mockStatic(File.class, 
Mockito.CALLS_REAL_METHODS)) {
+      files
+          .when(() -> File.createTempFile(anyString(), any(), any()))
+          .thenAnswer(
+              invocation -> {
+                tempFolders.add(invocation.getArgument(2));
+                return invocation.callRealMethod();
+              });
+      PipelineTestingUtil.execute(transform, 1, false);
+    }
+
+    assertEquals(0, transform.getErrors());
+    assertEquals(Set.of("old.txt", "new.txt"), entries(zip));
+    assertEquals(List.of(zipDir.toFile()), tempFolders, "temporary file 
folder");
+    assertEquals(
+        List.of(zip), Files.list(zipDir).toList(), "no temporary file should 
be left behind");
+  }
+
+  private static void writeZip(Path zip, String entry, String content) throws 
Exception {
+    try (ZipOutputStream out = new 
ZipOutputStream(Files.newOutputStream(zip))) {
+      out.putNextEntry(new ZipEntry(entry));
+      out.write(content.getBytes(StandardCharsets.UTF_8));
+      out.closeEntry();
+    }
+  }
+
+  private static Set<String> entries(Path zip) throws Exception {
+    Set<String> names = new TreeSet<>();
+    try (java.util.zip.ZipFile zipFile = new 
java.util.zip.ZipFile(zip.toFile())) {
+      zipFile.stream().forEach(entry -> names.add(entry.getName()));
+    }
+    return names;
+  }
+}
diff --git 
a/rap/src/main/java/org/apache/hop/ui/core/widget/svg/SvgLabelListenerImpl.java 
b/rap/src/main/java/org/apache/hop/ui/core/widget/svg/SvgLabelListenerImpl.java
index 9ff9de1920..b3d93c929f 100644
--- 
a/rap/src/main/java/org/apache/hop/ui/core/widget/svg/SvgLabelListenerImpl.java
+++ 
b/rap/src/main/java/org/apache/hop/ui/core/widget/svg/SvgLabelListenerImpl.java
@@ -35,6 +35,8 @@ public class SvgLabelListenerImpl extends ClientListener 
implements ISingletonPr
     super(getText());
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   private static String getText() {
     String canvasScript = null;
     try {
diff --git 
a/rap/src/main/java/org/apache/hop/ui/hopgui/HopWebServletContextListener.java 
b/rap/src/main/java/org/apache/hop/ui/hopgui/HopWebServletContextListener.java
index 2059071142..cd42cb5e0e 100644
--- 
a/rap/src/main/java/org/apache/hop/ui/hopgui/HopWebServletContextListener.java
+++ 
b/rap/src/main/java/org/apache/hop/ui/hopgui/HopWebServletContextListener.java
@@ -32,6 +32,8 @@ public class HopWebServletContextListener extends 
RWTServletContextListener {
   private static final Logger logger =
       Logger.getLogger(HopWebServletContextListener.class.getName());
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   @Override
   public void contextInitialized(ServletContextEvent event) {
     /*
diff --git a/ui/src/main/java/org/apache/hop/ui/core/dialog/ErrorDialog.java 
b/ui/src/main/java/org/apache/hop/ui/core/dialog/ErrorDialog.java
index b9639d7c23..6e51cddc7e 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/dialog/ErrorDialog.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/dialog/ErrorDialog.java
@@ -54,6 +54,8 @@ public class ErrorDialog extends Dialog {
     this(parent, title, message, throwable, Function.identity());
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public ErrorDialog(
       Shell parent,
       String title,
@@ -85,6 +87,8 @@ public class ErrorDialog extends Dialog {
     showErrorDialog(parent, title, message, exception, showCancelButton);
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   private void showErrorDialog(
       Shell parent, String title, String message, Exception exception, boolean 
showCancelButton) {
     if (parent.isDisposed()) {
diff --git 
a/ui/src/main/java/org/apache/hop/ui/core/gui/GuiCompositeWidgets.java 
b/ui/src/main/java/org/apache/hop/ui/core/gui/GuiCompositeWidgets.java
index c7167489cf..6a2dc521e6 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/gui/GuiCompositeWidgets.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/gui/GuiCompositeWidgets.java
@@ -1624,6 +1624,8 @@ public class GuiCompositeWidgets {
         || (parameterType == char.class && valueClass == Character.class);
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   private void getWidgetsData(Object sourceData, GuiElements guiElements) {
     if (guiElements.isIgnored()) {
       return;
diff --git a/ui/src/main/java/org/apache/hop/ui/core/widget/OsHelper.java 
b/ui/src/main/java/org/apache/hop/ui/core/widget/OsHelper.java
index c11a40da8c..28517417ab 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/widget/OsHelper.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/widget/OsHelper.java
@@ -98,6 +98,8 @@ public class OsHelper {
     return true;
   }
 
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
   public static void initOsHandlers(Display display) {
 
     // handle OpenDocument
diff --git a/ui/src/main/java/org/apache/hop/ui/util/SwtSvgImageUtil.java 
b/ui/src/main/java/org/apache/hop/ui/util/SwtSvgImageUtil.java
index 57ee5d793e..18d24e35d7 100644
--- a/ui/src/main/java/org/apache/hop/ui/util/SwtSvgImageUtil.java
+++ b/ui/src/main/java/org/apache/hop/ui/util/SwtSvgImageUtil.java
@@ -56,16 +56,18 @@ public class SwtSvgImageUtil {
 
   private static final String NO_IMAGE = "ui/images/no_image.svg";
 
-  private static FileObject base;
+  private static FileObject base = resolveBase();
 
   private static double zoomFactor = PropsUi.getInstance().getZoomFactor();
 
-  static {
+  // Safe: the stack trace goes to the local stderr only, never to a remote 
client
+  @SuppressWarnings("java:S4507")
+  private static FileObject resolveBase() {
     try {
-      base = 
HopVfs.getFileSystemManager().resolveFile(System.getProperty("user.dir"));
+      return 
HopVfs.getFileSystemManager().resolveFile(System.getProperty("user.dir"));
     } catch (FileSystemException e) {
       e.printStackTrace();
-      base = null;
+      return null;
     }
   }
 

Reply via email to