From a62e38133e31c49e0d840029a75382a1be2f0a9a Mon Sep 17 00:00:00 2001 From: "macroscopeapp[bot]" <170038800+macroscopeapp[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 20:59:09 +0000 Subject: [PATCH 1/2] Fix shell injection vulnerability in JavaagentAwareStartScriptGenerator by escaping agent options --- .../JavaagentAwareStartScriptGenerator.kt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/plugin/src/main/kotlin/com/ryandens/javaagent/JavaagentAwareStartScriptGenerator.kt b/plugin/src/main/kotlin/com/ryandens/javaagent/JavaagentAwareStartScriptGenerator.kt index 3c7819ee..900e842e 100644 --- a/plugin/src/main/kotlin/com/ryandens/javaagent/JavaagentAwareStartScriptGenerator.kt +++ b/plugin/src/main/kotlin/com/ryandens/javaagent/JavaagentAwareStartScriptGenerator.kt @@ -33,6 +33,7 @@ class JavaagentAwareStartScriptGenerator( platform.appHomeVar, platform.agentArgSeparator, optionsByFilePath, + platform, ), ) } @@ -62,6 +63,7 @@ class JavaagentAwareStartScriptGenerator( private val appHomeVar: String, private val agentArgSeparator: String, private val optionsByFilePath: Provider>, + private val platform: Platform, ) : Writer() { override fun close() { inner.close() @@ -79,6 +81,17 @@ class JavaagentAwareStartScriptGenerator( inner.write(cbuf, off, len) } + /** + * Escapes a javaagent option value for safe inclusion in shell scripts. + * - For Unix: wraps in single quotes, escaping internal single quotes with '\'' + * - For Windows: doubles percent signs to prevent variable expansion + */ + private fun escapeOptionValue(value: String): String = + when (platform) { + Platform.UNIX -> "'" + value.replace("'", "'\\''") + "'" + Platform.WINDOWS -> value.replace("%", "%%") + } + /** * Rewrites the javaagent placeholder that the templated `defaultJvmOpts` injects into the rendered start * script. When the configuration resolves to one or more agents, the single placeholder is replaced by one @@ -112,7 +125,7 @@ class JavaagentAwareStartScriptGenerator( files.joinToString( agentArgSeparator, ) { jar -> - val suffix = options[jar.canonicalPath]?.let { "=$it" } ?: "" + val suffix = options[jar.canonicalPath]?.let { "=" + escapeOptionValue(it) } ?: "" "-javaagent:$appHomeVar${pathSeparator}agent-libs$pathSeparator${jar.name}$suffix" }, ) From 51d4603abe686d3c6d723d60caf1a3e00637c642 Mon Sep 17 00:00:00 2001 From: "macroscopeapp[bot]" <170038800+macroscopeapp[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 21:05:50 +0000 Subject: [PATCH 2/2] Fix test expectation for Unix start script agent options with shell escaping --- .../com/ryandens/javaagent/JavaagentPluginFunctionalTest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/src/functionalTest/kotlin/com/ryandens/javaagent/JavaagentPluginFunctionalTest.kt b/plugin/src/functionalTest/kotlin/com/ryandens/javaagent/JavaagentPluginFunctionalTest.kt index dde977b5..ad1b22c6 100644 --- a/plugin/src/functionalTest/kotlin/com/ryandens/javaagent/JavaagentPluginFunctionalTest.kt +++ b/plugin/src/functionalTest/kotlin/com/ryandens/javaagent/JavaagentPluginFunctionalTest.kt @@ -284,9 +284,10 @@ DEFAULT_JVM_OPTS="\"-javaagent:${"$"}APP_HOME/agent-libs/simple-agent.jar\" \"-X assertTrue(applicationDistributionScript.readText().contains(expectedWindowsDefaultJvmOpts)) } else { // The option string rides inside the agent's own backslash-escaped quoted token -- see issue #95. + // Option values are wrapped in single quotes to prevent shell injection (issue #50). val expectedDefaultJavaOpts = """ -DEFAULT_JVM_OPTS="\"-javaagent:${"$"}APP_HOME/agent-libs/simple-agent.jar=12345:config.yaml\" \"-Xmx256m\"" +DEFAULT_JVM_OPTS="\"-javaagent:${"$"}APP_HOME/agent-libs/simple-agent.jar='12345:config.yaml'\" \"-Xmx256m\"" """ assertTrue(applicationDistributionScript.readText().contains(expectedDefaultJavaOpts)) }