diff --git a/src/main/java/org/codehaus/plexus/util/cli/Commandline.java b/src/main/java/org/codehaus/plexus/util/cli/Commandline.java index db145c50..bca41d30 100644 --- a/src/main/java/org/codehaus/plexus/util/cli/Commandline.java +++ b/src/main/java/org/codehaus/plexus/util/cli/Commandline.java @@ -581,9 +581,7 @@ public Process execute() throws CommandLineException { File workingDir = shell.getWorkingDirectory(); try { - if (workingDir == null) { - process = Runtime.getRuntime().exec(getCommandline(), environment, workingDir); - } else { + if (workingDir != null) { if (!workingDir.exists()) { throw new CommandLineException( "Working directory \"" + workingDir.getPath() + "\" does not exist!"); @@ -591,9 +589,31 @@ public Process execute() throws CommandLineException { throw new CommandLineException( "Path \"" + workingDir.getPath() + "\" does not specify a directory."); } + } - process = Runtime.getRuntime().exec(getCommandline(), environment, workingDir); + // Use ProcessBuilder instead of Runtime.exec() to avoid shell interpretation + // This prevents shell metacharacter expansion (e.g., *, ?, wildcards) + String[] commandline = getRawCommandline(); + ProcessBuilder processBuilder = new ProcessBuilder(commandline); + + if (workingDir != null) { + processBuilder.directory(workingDir); } + + // Set environment variables + if (environment != null && environment.length > 0) { + Map env = processBuilder.environment(); + for (String envVar : environment) { + int idx = envVar.indexOf('='); + if (idx > 0) { + String key = envVar.substring(0, idx); + String value = envVar.substring(idx + 1); + env.put(key, value); + } + } + } + + process = processBuilder.start(); } catch (IOException ex) { throw new CommandLineException("Error while executing process.", ex); } diff --git a/src/test/java/org/codehaus/plexus/util/cli/CommandlineTest.java b/src/test/java/org/codehaus/plexus/util/cli/CommandlineTest.java index 95862478..0a772f70 100644 --- a/src/test/java/org/codehaus/plexus/util/cli/CommandlineTest.java +++ b/src/test/java/org/codehaus/plexus/util/cli/CommandlineTest.java @@ -483,6 +483,43 @@ private static void createAndCallScript(File dir, String content) throws Excepti executeCommandLine(cmd); } + /** + * Test that asterisk and other special characters are NOT expanded by shell. + * This test verifies the fix for SCM-763 where passwords with asterisks were being expanded. + */ + @Test + void executeWithAsteriskInArgument() throws Exception { + Commandline cmd = new Commandline(); + cmd.setWorkingDirectory(baseDir); + cmd.setExecutable("echo"); + // Add an argument with asterisk that should NOT be expanded + cmd.createArg().setValue("S8p3r*S3cr3t"); + + Process process = cmd.execute(); + String output = IOUtil.toString(process.getInputStream()).trim(); + + // The output should contain the literal asterisk, not expanded files + assertEquals("S8p3r*S3cr3t", output); + } + + /** + * Test that question mark is NOT expanded by shell. + */ + @Test + void executeWithQuestionMarkInArgument() throws Exception { + Commandline cmd = new Commandline(); + cmd.setWorkingDirectory(baseDir); + cmd.setExecutable("echo"); + // Add an argument with question mark that should NOT be expanded + cmd.createArg().setValue("test?value"); + + Process process = cmd.execute(); + String output = IOUtil.toString(process.getInputStream()).trim(); + + // The output should contain the literal question mark, not expanded files + assertEquals("test?value", output); + } + /** * Execute the command line *