System command built from user-controlled sources¶
ID: swift/command-line-injection
Kind: path-problem
Security severity: 9.8
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-078
- external/cwe/cwe-088
Query suites:
- swift-code-scanning.qls
- swift-security-extended.qls
- swift-security-and-quality.qls
Click to see the query in the CodeQL repository
Constructing a system command with unsanitized user input is dangerous, since a malicious user may be able to craft input that executes arbitrary code.
Recommendation¶
If possible, use hard-coded string literals to specify the command to run. Instead of interpreting user input directly as command names, examine the input and then choose among hard-coded string literals.
If this is not possible, then add sanitization code to verify that the user input is safe before using it.
Example¶
The following example executes code from user input without sanitizing it first:
var task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", userControlledString] // BAD
task.launch()
If user input is used to construct a command it should be checked first. This ensures that the user cannot insert characters that have special meanings:
func validateCommand(_ command: String) -> String? {
let allowedCommands = ["ls -l", "pwd", "echo"]
if allowedCommands.contains(command) {
return command
}
return nil
}
if let validatedString = validateCommand(userControlledString) {
var task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", validatedString] // GOOD
task.launch()
}
References¶
OWASP: Command Injection.
Common Weakness Enumeration: CWE-78.
Common Weakness Enumeration: CWE-88.