HIGH command injectionfibergo

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 IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Can Command Injection occur if I use exec.Command with arguments as a slice in Fiber?
Yes, if any element in the argument slice is built by concatenating untrusted input with shell metacharacters or if you fall back to shell features (such as sh -c). Always validate each input and avoid the shell entirely.
Does middleBrick detect Command Injection in unauthenticated scans of Fiber APIs?
Yes, middleBrick scans the unauthenticated attack surface and flags endpoints that invoke external processes with user-influenced data, including patterns that suggest shell interpretation or insufficient input validation.