Command Injection in Fiber (Go)
Command Injection in Fiber with Go — how this specific combination creates or exposes the vulnerability
Command Injection occurs when an API endpoint constructs a system command using untrusted input without proper validation or escaping. In a Fiber application written in Go, this typically arises when developers use os/exec to invoke external commands and interpolate user-controlled data such as query parameters, headers, or body fields directly into the command string or arguments. Because Go does not automatically escape shell metacharacters, concatenating these values enables an attacker to terminate the intended command and inject additional shell commands.
For example, consider a health-check endpoint that pings a host provided by the caller. If the code uses exec.Command("ping", host) where host is taken directly from c.Query("host"), a value like 127.0.0.1; id can lead to arbitrary command execution on the underlying host. This is not a Fiber-specific issue, but Fiber’s idiomatic patterns—such as routing groups, middleware, and rapid prototyping—can encourage quick implementations that omit input validation or use shell features inadvertently.
Additionally, developers might use the shell for convenience (e.g., exec.Command("sh", "-c", "ping "+host)), which magnifies the risk because the shell interprets metacharacters like &, |, and $(). Even when arguments are passed as a slice, if any element is built from concatenated strings that include unsanitized input, the boundary between data and command can blur. The presence of OpenAPI specs with relaxed parameter definitions can further obscure the origin of untrusted data, making runtime validation essential.
middleBrick detects Command Injection by analyzing unauthenticated attack surfaces and correlating spec definitions with runtime behavior. It flags endpoints that invoke external processes with concatenated or partially trusted input, highlighting the risk even when the code appears to use argument slices. This is particularly relevant in microservice APIs where health endpoints, debug routes, or export functions may expose command execution paths.
Go-Specific Remediation in Fiber — concrete code fixes
To remediate Command Injection in Fiber with Go, always avoid the shell and treat external command invocation as a strict composition of executable plus arguments. Use exec.Command with separate arguments and never concatenate or interpolate untrusted data into a shell command string. Validate and sanitize inputs against an allowlist, and prefer structured data or safe libraries for operations like hostname resolution or file manipulation.
Example: Vulnerable Code
package main
import (
"github.com/gofiber/fiber/v2"
"os/exec"
)
func main() {
app := fiber.New()
app.Get("/ping", func(c *fiber.Ctx) error {
host := c.Query("host", "localhost")
// Vulnerable: host is used directly in command construction
cmd := exec.Command("ping", host)
out, err := cmd.Output()
if err != nil {
return c.Status(500).SendString("error")
}
return c.Send(out)
})
app.Listen(":3000")
}
Example: Remediated Code
package main
import (
"github.com/gofiber/fiber/v2"
"net"
"os/exec"
)
func safeHost(input string) (string, error) {
// Allowlist validation: only alphanumeric, dots, and hyphens for hostnames
// Reject any input containing shell metacharacters or path elements
if matched := net.ParseIP(input); matched != nil {
return input, nil
}
// Basic hostname pattern validation
// Note: for production, use a stricter allowlist and consider using a library
var allowed = regexp.MustCompile(`^[a-zA-Z0-9.-]+$`)
if !allowed.MatchString(input) {
return "", fmt.Errorf("invalid host")
}
return input, nil
}
func main() {
app := fiber.New()
app.Get("/ping", func(c *fiber.Ctx) error {
host := c.Query("host", "localhost")
safe, err := safeHost(host)
if err != nil {
return c.Status(400).SendString("invalid host")
}
// Safe: arguments are separate, no shell involved
cmd := exec.Command("ping", "-c", "4", safe)
out, err := cmd.Output()
if err != nil {
return c.Status(500).SendString("error")
}
return c.Send(out)
})
app.Listen(":3000")
}
Additional practices include avoiding sh -c or any shell invocation, using context timeouts on cmd to limit execution duration, and leveraging middleware to reject requests containing suspicious patterns (e.g., ;, &, |, `, $()). When integrating with CI/CD, the GitHub Action can enforce that no new endpoints introduce external command execution without explicit review, and the CLI can be used locally to scan for risky patterns in the codebase.
middleBrick’s LLM/AI Security checks are especially valuable when API endpoints expose generative features that might inadvertently encourage unsafe command construction. By combining input validation, strict argument lists, and continuous scanning, teams can significantly reduce the attack surface while maintaining the utility of external process invocation.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |