RSTR-INJ-005 — Go exec.Command("sh", "-c", ...)

Summary

exec.Command is being invoked with a shell wrapper — sh -c, bash -c, or cmd /c — so the second argument is interpreted as a shell line. Any attacker-controlled substring becomes shell syntax. Go's stdlib already protects you against this by accepting an argv list; the shell wrapper specifically opts back into the dangerous form.

Severity

High.

Languages

Go.

What rastray flags

exec.Command("sh", "-c", "ls " + path)            // ← flagged
exec.Command("bash", "-c", fmt.Sprintf("tar czf - %s", path))   // ← flagged
exec.Command("cmd", "/c", "dir " + path)          // ← flagged (Windows)

What rastray deliberately does not flag

  • exec.Command("ls", path) — argv form, no shell.
  • exec.Command("/usr/bin/curl", "-fsSL", url).

How to fix it

Drop the shell wrapper and pass arguments as separate strings — that is the safe form, no escaping required:

cmd := exec.Command("ls", path)
out, err := cmd.Output()
cmd := exec.Command("tar", "czf", "-", path)

If you genuinely need pipes or redirections, compose them in Go rather than letting the shell parse the command. io.Pipe plus two exec.Commands achieves a pipeline cleanly:

r, w := io.Pipe()
tar := exec.Command("tar", "czf", "-", path)
tar.Stdout = w
gpg := exec.Command("gpg", "--encrypt", "-r", recipient)
gpg.Stdin = r
// run both, close w when tar exits

References