Scanners detect OS command injection by adding shell separators and a harmless command to a parameter, then looking for command output, a timed delay, or an outside callback such as a DNS lookup. They miss cases where the input is filtered, the result is blind, or the vulnerable feature sits behind a step they cannot reach.
What command injection is
OWASP describes command injection as an attack whose goal is to execute arbitrary commands on the host operating system through a vulnerable application. It is possible when an application passes unsafe user data from forms, cookies or HTTP headers to a system shell. The commands usually run with the privileges of the vulnerable application. The testing guide adds that the impact can include unauthorized data access, data corruption and full server compromise.
It differs from code injection. In command injection the attacker extends something the application already does, running system commands, without adding their own code.
The signals scanners look for
The OWASP Web Security Testing Guide shows how a tester appends separators to a parameter: a pipe, a semicolon (sometimes URL encoded), or shell command substitution on Unix systems. A filename parameter, a directory parameter or a host name field are classic spots.
| Signal | How a scanner uses it | Limit |
|---|---|---|
| Visible output | Injects a harmless command and looks for its output in the response | Fails when the output is not returned |
| Time delay | Injects a command that pauses, then measures response time | Needs a reliable timing baseline |
| Out-of-band | Injects a command that makes a DNS or HTTP request to a server the tester controls, such as a name lookup | Fails if the server cannot reach the internet |
| Error change | Notes a different error or status after the separator | Easy to misread |
The testing guide includes a dedicated out-of-band section, using a name lookup against a controlled domain, which is the standard approach when nothing is returned to the browser.
Where scanners miss it
- Filters. The guide notes that developers often add filters, and that those are sometimes implemented badly. It describes attacker methods such as URL encoding, brace expansion and environment variables to slip past filters that block plain characters or particular commands. A scanner uses a limited set of these. A filter that blocks its set may still be bypassable by other methods.
- Blind injection with no outbound access. If output is not shown and the host cannot call out, timing is the only signal.
- Hidden inputs. Command injection may live in an upload filename, an image processing option, an HTTP header or a background job input that a crawl never touches.
- Argument injection. Even without a shell, user input can add options to a program. See argument injection explained.
- Indirect paths. Data stored now and used by a scheduled task later does not show in the next response.
What to do about it
- Avoid calling a shell at all. Use a library function for the job, such as a language API for the task.
- If you must run a program, pass arguments as a list and not as one string. See avoiding the shell.
- Validate with an allow-list: a pattern of lowercase letters and digits within a set length, with no metacharacters, is the sort of pattern OWASP's cheat sheet gives.
- Run the process with the least privilege that works.
- Treat a scanner hit as confirmed only after reproducing it in a test copy.
How static analysis helps
A static scan finds calls that build a command from user data in code. That covers inputs that a crawl never reaches. It cannot show whether the path is live in your deployment, so combine it with a dynamic test. Our post on SAST, DAST and IAST by vulnerability type lays out the split.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how a finding records the request and response it relied on.
Quick check
Does a clean DAST result rule out command injection?
No. Filters, blind behavior and unreachable inputs can all hide it. Pair the scan with code review for any place a program is launched.
Is an input filter a fix?
OWASP notes filters are often bypassed. Treat them as a supporting layer and fix by not building shell commands from user data.
Safeguard offers a free scan at gold.safeguard.sh/scan for your dependencies.
Sources
- OWASP: Command Injection
- OWASP WSTG: Command Injection
- OWASP Injection Prevention Cheat Sheet
- CWE-78: OS Command Injection
Last reviewed: 19 October 2026.