How to fix Command Injection
in Vapor (Swift)
Executive Summary
Command Injection in Vapor occurs when untrusted user input is passed directly into system execution sinks like `Process` or custom shell wrappers. When input is concatenated into a shell string, attackers use metacharacters like `;`, `&`, or `|` to break out of the intended command and execute arbitrary code with the privileges of the Swift process.
The Vulnerable Pattern
app.get("lookup") { req -> String in
let domain = req.query["domain"] ?? "google.com"
let process = Process()
process.executableURL = URL(fileURLWithPath: "/bin/sh")
// VULNERABLE: String interpolation inside a shell command string
process.arguments = ["-c", "nslookup \(domain)"]
let pipe = Pipe()
process.standardOutput = pipe
try process.run()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
return String(data: data, encoding: .utf8) ?? ""
}
The Secure Implementation
The exploit vector is the shell's command parser. By using `sh -c`, the input is interpreted for control characters. The fix involves: 1. Eliminating the shell intermediary by invoking the target binary (`/usr/bin/nslookup`) directly via `executableURL`. 2. Passing user input as separate elements in the `arguments` array. This forces the OS to treat the input as a literal string argument rather than executable code. 3. Implementing a strict allow-list regex to validate the input format before it ever reaches the system sink.
app.get("lookup") { req -> String in
guard let domain = req.query["domain"],
domain.range(of: "^[a-zA-Z0-9.-]+$", options: .regularExpression) != nil else {
throw Abort(.badRequest, reason: "Invalid domain format")
}
let process = Process()
// SECURE: Call the binary directly, avoiding /bin/sh entirely
process.executableURL = URL(fileURLWithPath: "/usr/bin/nslookup")
// SECURE: Pass arguments as a discrete [String] array; no shell parsing occurs
process.arguments = [domain]
let pipe = Pipe()
process.standardOutput = pipe
try process.run()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
return String(data: data, encoding: .utf8) ?? ""
}
Your Vapor (Swift) API
might be exposed to Command Injection
74% of Vapor (Swift) apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
Free Tier • No Credit Card • Instant Report
Verified by Ghost Labs Security Team
This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.