| name | command-injection-anti-pattern |
| description | Security anti-pattern for OS Command Injection vulnerabilities (CWE-78). Use when generating or reviewing code that executes shell commands, runs system processes, or handles user input in command-line operations. Detects shell string concatenation and recommends argument arrays. |
Command Injection Anti-Pattern
Severity: Critical
Summary
Command injection allows attackers to execute arbitrary OS commands by manipulating user input. This anti-pattern occurs when applications concatenate user input into shell command strings. Common in AI-generated code. Enables complete system compromise, data exfiltration, malware installation, and lateral movement.
The Anti-Pattern
User input embedded in shell command strings enables command injection. The shell cannot distinguish between intended commands and attacker-injected commands.
BAD Code Example
import os
def ping_host(hostname):
command = "ping -c 4 " + hostname
os.system(command)
GOOD Code Example
import subprocess
def ping_host(hostname):
import re
if not re.match(r'^[a-zA-Z0-9.-]+$', hostname):
raise ValueError("Invalid hostname format")
try:
subprocess.run(["ping", "-c", "4", hostname], check=True, shell=False)
except subprocess.CalledProcessError as e:
print(f"Error executing ping: {e}")
JavaScript/Node.js Examples
BAD:
const { exec } = require('child_process');
function pingHost(hostname) {
exec(`ping -c 4 ${hostname}`, (error, stdout) => {
console.log(stdout);
});
}
GOOD:
const { execFile } = require('child_process');
function pingHost(hostname) {
if (!/^[a-zA-Z0-9.-]+$/.test(hostname)) {
throw new Error('Invalid hostname format');
}
execFile('ping', ['-c', '4', hostname], (error, stdout) => {
if (error) {
console.error(`Error: ${error.message}`);
return;
}
console.log(stdout);
});
}
Java Examples
BAD:
public void pingHost(String hostname) {
try {
String command = "ping -c 4 " + hostname;
Runtime.getRuntime().exec(command);
} catch (IOException e) {
e.printStackTrace();
}
}
GOOD:
import java.io.IOException;
import java.util.regex.Pattern;
public void pingHost(String hostname) {
if (!Pattern.matches("^[a-zA-Z0-9.-]+$", hostname)) {
throw new IllegalArgumentException("Invalid hostname format");
}
try {
ProcessBuilder pb = new ProcessBuilder("ping", "-c", "4", hostname);
Process process = pb.start();
process.waitFor();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
Detection
Python:
os.system() with any user input
subprocess.run() or subprocess.Popen() with shell=True
- String concatenation:
"command " + user_input
- f-strings:
f"command {user_input}"
JavaScript/Node.js:
child_process.exec() with user input
- Template literals:
`command ${userInput}`
- String concatenation:
"command " + userInput
Java:
Runtime.getRuntime().exec() with string concatenation
- Single string argument to
exec() instead of string array
PHP:
exec(), system(), shell_exec(), passthru() with user input
- String concatenation:
"command " . $userInput
Search Patterns:
- Grep:
shell=True|exec\(|system\(|child_process\.exec
- Look for user input variables in command construction
- Check for string concatenation or interpolation with command functions
Prevention
Testing for Command Injection
Manual Testing:
- Test shell metacharacters:
;, |, &, $(), `, &&, ||
- Input payloads:
; ls, | whoami, & cat /etc/passwd, `id`
- Verify commands execute safely without shell interpretation
- Confirm metacharacters treated as literal strings
Automated Testing:
- Static Analysis: Semgrep, Bandit (Python), ESLint security plugins, SpotBugs (Java)
- DAST: Burp Suite, OWASP ZAP with command injection payloads
- Code Review: Search for detection patterns above
Example Test:
def test_command_injection_prevention():
malicious_input = "google.com; rm -rf /"
try:
ping_host(malicious_input)
assert False, "Should reject malicious input"
except ValueError:
pass
Remediation Steps
- Identify vulnerable code - Use detection patterns above
- Validate necessity - Can you avoid shell commands entirely?
- Replace with safe API - Use language-specific libraries when possible
- Convert to argument arrays - Replace string concatenation
- Remove shell=True - Never use with user input
- Add input validation - Allowlist known-good patterns
- Test the fix - Verify shell metacharacters are literal
- Review similar code - Check for pattern across codebase
Related Security Patterns & Anti-Patterns
References