Command injection is when untrusted input is inserted into a shell command your server runs, letting an attacker append their own commands. Because the shell interprets characters like semicolons and pipes, input such as file.txt; rm -rf / can turn one intended command into several, giving the attacker control of the server.
Why the shell is the danger
Running a command through a shell means the shell parses the whole string, so any special character in the input is interpreted, not treated as data. Building the command by pasting input into a string is what opens the door; the shell does the rest.
The safe pattern
Do not build a shell string from input. Pass the program and its arguments as a list so the input is handed to the program as data, never parsed by a shell. In Node, avoid exec with an interpolated string and use execFile or spawn with an args array; in Python, avoid shell=True and pass a list to subprocess.run.
What this means for AI-generated code
String interpolation into a shell command is the most natural way to write it, and it works perfectly in a demo with clean input. The AI tool has no signal that the input will ever be hostile, so it ships the interpolated version.
Common questions
What is the safe way to run a subprocess in Node.js?
Use child_process.execFile() or spawn() with the command and arguments as separate strings, not concatenated into one. This bypasses the shell entirely — the OS calls the program directly with the arguments as data. Never use exec() with interpolated user input.
What is the safe way to run a subprocess in Python?
Pass subprocess.run() a list of strings, not a single string with shell=True. subprocess.run(['convert', input_file, output_file]) is safe; subprocess.run('convert ' + input_file, shell=True) is not. With a list and no shell, the OS passes each argument directly without shell parsing.
Are there common AI-generated code patterns that introduce command injection?
Yes: file conversion utilities that pass user-supplied filenames to a system call, image processing that shells out with a filename from a request, and server administration scripts that use os.system() or child_process.exec() with values from an API parameter. Any place a file path or name from user input reaches a shell command is a candidate.