From 1b2a356c88618af82a0dea0358ef63e88d5bb690 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Fri, 29 May 2026 13:22:50 -0700 Subject: [PATCH 1/3] Migrate from ProcessBuilder to LabKeyProcessBuilder --- api/src/org/labkey/api/pipeline/PipelineJob.java | 10 +++++----- api/src/org/labkey/api/util/LabKeyProcessBuilder.java | 5 +++++ .../labkey/pipeline/api/PipelineJobServiceImpl.java | 3 ++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/api/src/org/labkey/api/pipeline/PipelineJob.java b/api/src/org/labkey/api/pipeline/PipelineJob.java index 215a88e2a21..d30b06ce9a8 100644 --- a/api/src/org/labkey/api/pipeline/PipelineJob.java +++ b/api/src/org/labkey/api/pipeline/PipelineJob.java @@ -53,6 +53,7 @@ import org.labkey.api.util.GUID; import org.labkey.api.util.Job; import org.labkey.api.util.JsonUtil; +import org.labkey.api.util.LabKeyProcessBuilder; import org.labkey.api.util.NetworkDrive; import org.labkey.api.util.QuietCloser; import org.labkey.api.util.URLHelper; @@ -81,7 +82,6 @@ import java.nio.file.StandardOpenOption; import java.sql.Time; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.List; @@ -101,7 +101,7 @@ @JsonIgnoreProperties(value={"_logFilePathName"}, allowGetters = true) //Property removed. Added here for backwards compatibility abstract public class PipelineJob extends Job implements Serializable, ContainerUser { - public static final FileType FT_LOG = new FileType(Arrays.asList(".log"), ".log", Arrays.asList("text/plain")); + public static final FileType FT_LOG = new FileType(List.of(".log"), ".log", List.of("text/plain")); public static final String PIPELINE_EMAIL_ADDRESS_PARAM = "pipeline, email address"; public static final String PIPELINE_USERNAME_PARAM = "pipeline, username"; @@ -1259,7 +1259,7 @@ private PrintWriter createPrintWriter(@Nullable FileLike outputFile, boolean app } } - public void runSubProcess(ProcessBuilder pb, FileLike dirWork) throws PipelineJobException + public void runSubProcess(LabKeyProcessBuilder pb, FileLike dirWork) throws PipelineJobException { runSubProcess(pb, dirWork, null, 0, false); } @@ -1268,13 +1268,13 @@ public void runSubProcess(ProcessBuilder pb, FileLike dirWork) throws PipelineJo * If logLineInterval is greater than 1, the first logLineInterval lines of output will be written to the * job's main log file. */ - public void runSubProcess(ProcessBuilder pb, FileLike dirWork, FileLike outputFile, int logLineInterval, boolean append) + public void runSubProcess(LabKeyProcessBuilder pb, FileLike dirWork, FileLike outputFile, int logLineInterval, boolean append) throws PipelineJobException { runSubProcess(pb, dirWork, outputFile, logLineInterval, append, 0, null); } - public void runSubProcess(ProcessBuilder pb, FileLike dirWork, FileLike outputFile, int logLineInterval, boolean append, long timeout, TimeUnit timeoutUnit) + public void runSubProcess(LabKeyProcessBuilder pb, FileLike dirWork, FileLike outputFile, int logLineInterval, boolean append, long timeout, TimeUnit timeoutUnit) throws PipelineJobException { Process proc; diff --git a/api/src/org/labkey/api/util/LabKeyProcessBuilder.java b/api/src/org/labkey/api/util/LabKeyProcessBuilder.java index e27a2c92110..5cb9dfcdf09 100644 --- a/api/src/org/labkey/api/util/LabKeyProcessBuilder.java +++ b/api/src/org/labkey/api/util/LabKeyProcessBuilder.java @@ -100,4 +100,9 @@ public static boolean isSecret(String propertyName) return lc.contains("secret") || lc.contains("password") || lc.contains("apikey") || lc.contains("_key") || lc.contains("token") || (secrets != null && secrets.isRegisteredSecret(propertyName)); } + + public void redirectOutput(ProcessBuilder.Redirect redirect) + { + _pb.redirectOutput(redirect); + } } diff --git a/pipeline/src/org/labkey/pipeline/api/PipelineJobServiceImpl.java b/pipeline/src/org/labkey/pipeline/api/PipelineJobServiceImpl.java index a6728f6b850..c3cb9d8beb1 100644 --- a/pipeline/src/org/labkey/pipeline/api/PipelineJobServiceImpl.java +++ b/pipeline/src/org/labkey/pipeline/api/PipelineJobServiceImpl.java @@ -70,6 +70,7 @@ import org.labkey.api.security.permissions.InsertPermission; import org.labkey.api.util.FileUtil; import org.labkey.api.util.JunitUtil; +import org.labkey.api.util.LabKeyProcessBuilder; import org.labkey.api.util.MemTracker; import org.labkey.api.util.MinorConfigurationException; import org.labkey.api.util.NetworkDrive; @@ -945,7 +946,7 @@ private String getPathToTool(@Nullable String installPath, String rel, boolean e private String getToolsPath() { String toolsDir = getAppProperties().getToolsDirectory(); - CaseInsensitiveHashMap ciEnvMap = new CaseInsensitiveHashMap<>((new ProcessBuilder()).environment()); + CaseInsensitiveHashMap ciEnvMap = new CaseInsensitiveHashMap<>((new LabKeyProcessBuilder()).environment()); String path = ciEnvMap.get("PATH"); return toolsDir + File.pathSeparator + path; } From 334e3974a120a1736c9fe6e23b75da7f1173c105 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Fri, 29 May 2026 13:45:16 -0700 Subject: [PATCH 2/3] Migrate from ProcessBuilder to LabKeyProcessBuilder --- .../src/org/labkey/pipeline/analysis/CommandTaskImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pipeline/src/org/labkey/pipeline/analysis/CommandTaskImpl.java b/pipeline/src/org/labkey/pipeline/analysis/CommandTaskImpl.java index 460727f4254..fb22c608d13 100644 --- a/pipeline/src/org/labkey/pipeline/analysis/CommandTaskImpl.java +++ b/pipeline/src/org/labkey/pipeline/analysis/CommandTaskImpl.java @@ -622,7 +622,7 @@ public RecordedActionSet run() throws PipelineJobException // Input file location must be determined before creating the process command. if (!_factory.getInputPaths().isEmpty()) { - try (WorkDirectory.CopyingResource lock = _wd.ensureCopyingLock()) + try (WorkDirectory.CopyingResource _ = _wd.ensureCopyingLock()) { for (Map.Entry entry : _factory.getInputPaths().entrySet()) { @@ -733,7 +733,7 @@ protected boolean runCommand(RecordedAction action, @Nullable String apiKey, @Nu action.setStartTime(new Date()); action.addParameter(RecordedAction.COMMAND_LINE_PARAM, commandLine); int timeout = _factory._timeout != null ? _factory._timeout : 0; - getJob().runSubProcess(pb.processBuilder(), _wd.getDir(), fileOutput, lineInterval, false, timeout, TimeUnit.SECONDS); + getJob().runSubProcess(pb, _wd.getDir(), fileOutput, lineInterval, false, timeout, TimeUnit.SECONDS); action.setEndTime(new Date()); return true; } From 266a54f34f21afa3290866a4b9285093ed48252c Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Fri, 29 May 2026 15:02:31 -0700 Subject: [PATCH 3/3] Misc polish --- api/src/org/labkey/api/util/LabKeyProcessBuilder.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/api/src/org/labkey/api/util/LabKeyProcessBuilder.java b/api/src/org/labkey/api/util/LabKeyProcessBuilder.java index 5cb9dfcdf09..ff0dad48356 100644 --- a/api/src/org/labkey/api/util/LabKeyProcessBuilder.java +++ b/api/src/org/labkey/api/util/LabKeyProcessBuilder.java @@ -6,6 +6,7 @@ import java.io.File; import java.io.IOException; import java.util.List; +import java.util.Locale; import java.util.Map; /** @@ -16,8 +17,7 @@ *

Variables are removed (silently) if their name: *

    *
  • matches any property name registered with {@link SecretService}, or
  • - *
  • contains "secret" (case-insensitive), or
  • - *
  • contains "password" (case-insensitive).
  • + *
  • contains (case-insensitive) any of "secret", "password", "apikey", "_key", or "token".
  • *
* *

Use this class wherever {@link ProcessBuilder} would otherwise be used. An IntelliJ inspection @@ -96,13 +96,14 @@ private void sanitizeEnvironment() public static boolean isSecret(String propertyName) { SecretService secrets = ServiceRegistry.get().getService(SecretService.class); - String lc = propertyName.toLowerCase(); + String lc = propertyName.toLowerCase(Locale.ROOT); return lc.contains("secret") || lc.contains("password") || lc.contains("apikey") || lc.contains("_key") || lc.contains("token") || (secrets != null && secrets.isRegisteredSecret(propertyName)); } - public void redirectOutput(ProcessBuilder.Redirect redirect) + public LabKeyProcessBuilder redirectOutput(ProcessBuilder.Redirect redirect) { _pb.redirectOutput(redirect); + return this; } }