Skip to content

Java: detect command injection through delegating launchers - #22818

Draft
owen-mc with Copilot wants to merge 4 commits into
mainfrom
copilot/fix-is-safe-command-argument
Draft

owen-mc with Copilot wants to merge 4 commits into
mainfrom
copilot/fix-is-safe-command-argument

Conversation

Copilot AI commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

isSafeCommandArgument treated non-first arguments as safe whenever the executable was not a recognized shell. Delegating launchers could therefore execute attacker-controlled arguments without producing a command-line injection alert.

  • Detection

    • Distinguish delegating launchers from shells.
    • Recognize env, sudo, xargs, chroot, nice, nohup, setsid, stdbuf, and timeout.
    • Apply detection to array literals, mutable arrays, and command lists.
  • Coverage

    • Add an alert case for each recognized launcher.
    • Preserve safe handling for non-delegating commands such as cp.
Runtime.getRuntime().exec(new String[]{"env", userControlledInput});

Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix isSafeCommandArgument to account for delegating launchers Java: detect command injection through delegating launchers Oct 14, 2026
Copilot AI requested a review from owen-mc October 14, 2026 10:42
*/
private predicate isDelegatingLauncher(Expr ex) {
exists(string cmd | cmd = ex.(StringLiteral).getValue() |
cmd.regexpMatch("(.*/)?(chroot|env|nice|nohup|setsid|stdbuf|sudo|timeout|xargs)$")
@github-actions github-actions Bot added the Java label Oct 14, 2026
i > 0 and
not isShell(ai.getInit(0))
not isShell(ai.getInit(0)) and
not isDelegatingLauncher(ai.getInit(0))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new check disables sanitization for every argument after a launcher. For example:

new ProcessBuilder(new String[]{"env", "/bin/cp", userInput, "/tmp/destination"});

This now produces java/command-line-injection, although userInput remains a discrete argument to the fixed /bin/cp executable. This contradicts the safe direct-cp behavior tested at Test.java:48 and introduces false positives into a high-precision query.

Make launcher handling position-aware: flag the operand selecting the delegated command, then preserve normal safe-argument handling once a fixed non-shell command is known. Add GOOD cases for array literals, lists, and mutable arrays.

*/
private predicate isDelegatingLauncher(Expr ex) {
exists(string cmd | cmd = ex.(StringLiteral).getValue() |
cmd.regexpMatch("(.*/)?(chroot|env|nice|nohup|setsid|stdbuf|sudo|timeout|xargs)$")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Common launchers such as flock, su, runuser, doas, and time remain unrecognized. For example, taint in {"flock", "/tmp/lock", userInput} is still sanitized even though userInput selects the executed command. This matches the existing unresolved review thread.

@owen-mc

owen-mc commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

@copilot Please address the three comments on this PR.

Copilot AI and others added 2 commits October 14, 2026 11:25
Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>
Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>

Copilot AI commented Oct 14, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please address the three comments on this PR.

Addressed all three comments in edb67fe and 866d93b. Launcher handling now preserves safe arguments after fixed non-shell commands, recognizes the missing wrappers, and includes GOOD cases for literals, lists, and mutable arrays. Added safeguards and regressions for unresolved commands and mutated aliases. All four CWE-078 tests pass; final read-only review found no issues. The automated security scan was skipped because its database was too large.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants