Get the value of a variable inside processBuilder in java

262 views Asked by At

I want to download the file from s3 bucket using aws s3 cli command with process builder. The code is below. If I do not want to hardcode the file name I am getting the error. Can anyone please let me know how to pass the variable inside a command.

public static void main(String[] args) {
    ProcessBuilder processBuilder = new ProcessBuilder();
    Map<String, String> env = processBuilder.environment();
    System.out.println(env);
    String fileName = "NBN-20210623000000000001";

    // Checking if the system is windows or not
    if (System.getProperty("os.name")
            .startsWith("Windows")) {
        // processBuilder.command("cmd.exe", "/c", "echo %cd%");
        // Need to pass the cli commands to download the file based on the --profile
        processBuilder.command("cmd.exe", "/c",
                "aws s3 cp s3://npis-sam-deal-calculator/estimate/ASI000000000042/AsynchronousProcess/${fileName} src/main/resources/ --profile npis-dev-np");
    } else {
        // In pipeline the environment is on unix so need to get the profile from the
        // environment variable
        processBuilder.command("/bin/bash", "-c",
                "aws s3 cp s3://npis-sam-deal-calculator/pricelist/dcpl.csv src/test/resources/ --profile ${aws_profile}");
    }

    try {
        Process process = processBuilder.start();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }

        int exitCode = process.waitFor();
        System.out.println("\nExited with error code : " + exitCode);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

If you see, I am declaring the variable in fileName. However, using fileName in s3 commands for windows I am unable to download the file. What can be done to resolve the issue?

1

There are 1 answers

0
Matt On

Your approach will potentially create a command injection vulnerability if the inputs (fileName and aws_profile) are not properly sanitized. Use caution and be careful. Someone with control over these parameters could execute arbitrary commands on the invoked shell. Another way to interact with AWS S3 would be to use the AWS SDK for Java.


Java won't replace ${fileName} inside your command-string with the filename. You can use string concatenation to put the filename inside the command. Remember to sanitize fileName if you don't have absolute control over its content.

String fileName = "NBN-20210623000000000001";
String command = "aws s3 cp" +
        " s3://npis-sam-deal-calculator/estimate/ASI000000000042/AsynchronousProcess/" +
        fileName +
        " src/main/resources/" +
        " --profile npis-dev-np";

processBuilder.command("cmd.exe", "/c", command);

To insert an environment variable, you can do this safely like this:

String awsProfile = System.getenv("aws_profile"); // OS independent
// sanitize awsProfile
String command = "aws s3 cp" +
        " s3://npis-sam-deal-calculator/pricelist/dcpl.csv" +
        " src/test/resources/" +
        " --profile " + awsProfile;

processBuilder.command("/bin/bash", "-c", command);