flawopen.com/Command Injection/Python subprocess
Not if any part of the command string includes untrusted input. shell=True runs the command through an actual shell, which means shell metacharacters (;, |, &&, backticks) in the input can chain in additional commands.
# filename from user upload
subprocess.run(
f"convert {filename} out.png",
shell=True
)# no shell, args passed as a list
subprocess.run(
["convert", filename, "out.png"]
)Without shell=True, subprocess.run() executes the program directly with the given argument list — there's no shell parsing the string, so characters like ; or | in filename are passed literally as part of that one argument, never interpreted as command separators.
It's a real mitigation but a weaker one than avoiding the shell entirely — it requires quoting every single interpolated value correctly, with no structural guarantee if one is missed. Avoiding shell=True is the more robust default.
Yes — os.system() always runs through a shell, so it carries this risk unconditionally whenever it includes untrusted input.