The Risk
When code constructs a system command by concatenating user input and hands it to a shell, the shell interprets special characters such as semicolons, pipes, and backticks. An attacker can use these to append extra commands that run with your service privileges. This is command injection, and it can lead to full server compromise.
The root cause is mixing untrusted data with an interpreter that treats some characters as control syntax.
The Defense
- Avoid the shell entirely. Call the program directly and pass arguments as a separate list so no string is parsed for metacharacters.
- Never assemble a single command string from user input.
- Use language libraries for the task instead of shelling out when one exists.
- Apply an allowlist for any value that must influence behavior, such as a fixed set of options.
- Drop privileges and constrain the environment so an escape gains little.
Key idea
Pass user data as discrete arguments to a program rather than building a shell command string, so control characters can never become new commands.