Shell Injection

Shell injection, also called OS command injection, is an attack in which untrusted input is passed to an operating-system shell and ends up being interpreted as a command. OWASP defines command injection as “an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application.” The vulnerability is especially dangerous in scripting and automation contexts, where programs frequently shell out to run external utilities, and where a single injected command can read files, exfiltrate data, or take over a host.

The flaw appears when a developer constructs a shell command by gluing together a fixed program name with user-supplied data and hands the whole string to a shell. Functions such as C’s system() or PHP’s system() pass their argument through a shell interpreter, so any shell metacharacters in the input - the semicolon, pipe, ampersand, backtick, or double-ampersand and double-pipe operators - are treated as command syntax rather than data. An attacker who controls part of that string can chain a second command onto the legitimate one. OWASP lists the common entry points for the tainted input: form parameters, cookie values, HTTP headers, command-line arguments, and environment variables.

The consequences scale with the privileges of the vulnerable process. OWASP notes that if the application runs with elevated privileges - for example a setuid program - the injected commands execute with those same permissions, opening the door to privilege escalation, reading protected files such as /etc/shadow, deleting data, or modifying system configuration. Because automation often runs unattended and with broad access to a system, a shell-injection flaw in a deployment script or a runbook step can be catastrophic.

OWASP’s primary mitigation is to avoid the shell entirely: “use language-native APIs instead of shell commands.” Rather than invoking a mail binary through a shell, for instance, a program should call a library that performs the same function directly, removing the shell from the path and with it the chance to inject. When a shell call is genuinely unavoidable, the guidance is to validate input against a strict whitelist of allowed characters rather than trying to blacklist dangerous ones, since blacklists are easy to evade. Avoiding constructs like eval and never building command strings by concatenating untrusted values are core defensive practices.

Shell injection is a sibling of SQL injection and other code-injection flaws: in each case data crosses a boundary and is mistakenly interpreted as code by some interpreter. It appears on OWASP’s lists of common web-application risks and remains a recurring problem in glue code, CI/CD pipelines, and automation scripts - exactly the places where the convenience of “just run this command” tempts developers to build command strings from whatever input they happen to have.

Sources

Last verified June 8, 2026