Skip to content

Security: Fix Shell Injection in IoUtils and Harden Docker Container #2933

@RinZ27

Description

@RinZ27

Summary

This issue details the security improvements proposed in PR #2932, specifically addressing a potential shell injection vulnerability in IoUtils and hardening the Docker container configuration.

1. Shell Injection in IoUtils.runCommand(String)

The Vulnerability:
The existing implementation of IoUtils.runCommand(String command) wraps the input command in a shell execution:

// IoUtils.java
if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).startsWith("windows")) {
    finalizedCommand = new String[]{"cmd.exe", "/c", command};
} else {
    finalizedCommand = new String[]{"sh", "-c", command};
}

This pattern is susceptible to Shell Injection if any part of the command string is derived from untrusted user input. Because the command is passed as a single string to the shell (sh -c or cmd.exe /c), shell metacharacters (like ;, |, &&, $()) are interpreted by the shell.

Exploitation Example (PoC):
Imagine a scenario where IoUtils.runCommand is used to echo a user-provided value:

String userInput = "test; cat /etc/passwd"; // Malicious input
// Intended: echo "test; cat /etc/passwd"
// Actual execution: echo test; cat /etc/passwd
IoUtils.runCommand("echo " + userInput); 
  • Result: The shell executes echo test successfully, and then proceeds to execute cat /etc/passwd, leaking sensitive system file contents.
  • Impact: Arbitrary Code Execution (ACE) with the privileges of the Java process.

The Fix:
The PR introduces a new overload IoUtils.runCommand(String[] command) that utilizes ProcessBuilder directly with an argument array. This bypasses the shell entirely, treating arguments as literal strings.

// Safe usage
String[] cmd = {"echo", userInput};
IoUtils.runCommand(cmd, ...);

In this case, ProcessBuilder passes "test; cat /etc/passwd" as a single argument to echo, resulting in the safe output of the literal string, preventing the injection.

2. Docker Container Hardening

Root User Risk:
By default, Docker containers run as root. If the smithy process inside the container is compromised (e.g., via the shell injection above or another vulnerability), the attacker gains root privileges within the container. This significantly increases the attack surface for container escapes (e.g., exploiting kernel vulnerabilities) or modifying container-system files.

The Fix:

  • Non-Root User: Created a dedicated smithy user and switched to it using USER smithy. This adheres to the Principle of Least Privilege.
  • Health Check: Added a HEALTHCHECK instruction to ensure the container status accurately reflects the application state, aiding in orchestration and monitoring availability.

CC: @sugmanue - Here are the details and PoC you requested.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions