Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ private BashFunctionResult callFunctionUnBounded(String classpathResource, Strin
// Builds complete bash command with args
private String buildFullCommand(String scriptContent, String functionName, String... args) {
String variableAssignments = IntStream.range(0, args.length)
.mapToObj(i -> String.format("arg%d=\"%s\"", i + 1, args[i]))
.mapToObj(i -> String.format("arg%d=%s", i + 1, shellEscape(args[i])))
.collect(Collectors.joining("\n"));

String functionCall = functionName
Expand All @@ -88,6 +88,35 @@ private String buildFullCommand(String scriptContent, String functionName, Strin
return scriptContent + "\n" + variableAssignments + "\n" + functionCall;
}

/**
* Escapes a string for safe use in a Bash single-quoted context.
* Uses POSIX standard escaping: wraps the value in single quotes and escapes
* any single quotes within the value as '\'' (end quote, escaped quote, start quote).
*
* This prevents OS command injection via:
* - Command substitution: $(...) and `...`
* - Variable expansion: $VAR, ${VAR}
* - Arithmetic expansion: $((...))
* - Process substitution: <(...), >(...)
* - Glob patterns: *, ?, [...]
* - History expansion: !...
*
* Security Note: Single quotes in Bash prevent ALL interpretation of special
* characters, making this the most secure way to pass untrusted data to shell commands.
*
* @param value the string to escape (may be null)
* @return the shell-escaped string safe for bash argument assignment
*/
String shellEscape(String value) {
if (value == null) {
return "''";
}
// Replace each single quote with: '\'' (end current quote, add escaped quote, start new quote)
// This is the standard POSIX way to include a single quote in a single-quoted string
String escaped = value.replace("'", "'\\''");
return "'" + escaped + "'";
}

// Returns fallback if string is blank
private String fallbackIfBlank(String value, String fallback) {
return (value == null || value.isBlank()) ? fallback : value;
Expand Down
Loading