12

I understand why using 'shell=True' can be a security risk if you have untrusted input. However, I don't understand how 'shell=False' avoids the same risks.

Presumably if I wanted to allow a user to provide an input he might input: var="rm -rf /"

My code might simply:

subprocess.call(var,shell=True) # bad stuff

Or I might do:

varParts=var.split()
subprocess.call(varParts,shell=False) # also bad, right?

It would seem that the assumption is one wouldn't go through the trouble of processing the input as I did in the second example and therefore this would/could not happen?

3
  • ummmm any time you are passing untrusted input as a call you are running significant risks .... where did you hear shell = False makes it safe? docs.python.org/2/library/… ... all it does is stop shell injection which is just one attack ... Commented Jan 9, 2014 at 0:33
  • 2
    The very link you provided has a note that says "Warning: Invoking the system shell with shell=True can be a security hazard if combined with untrusted input." That implies to me that using shell=False provides some defense against that. Commented Jan 9, 2014 at 4:01
  • It is worth noting that you should use shlex.split rather than str.split methods as shlex will properly handle escaping in quotes and spaces Commented Dec 22, 2020 at 20:06

1 Answer 1

22

With shell=False, the args[0] is the program to be executed and args[1:] are passed as arguments to this program.

So, for example,

subprocess.call(['cat','nonexistent;','rm','-rf'])

calls the cat program and sends the 3 strings 'nonexistent;','rm','-rf' as arguments to cat. This is perfectly safe, though invalid since -r is an invalid option to cat.

However, arbitrary user input could still be unsafe. If, for example, you were to allow the user to control the program to be called, as in

subprocess.call(['rm','-rf'])
Sign up to request clarification or add additional context in comments.

3 Comments

That's good information. So I guess the use case for user input would be to allow a user to 'complete' a predefined command but not to 'provide' one. I am using an XML file to provide some shell command which allows me to test that some arbitrary condition is met within the operating system. The command could possibly be a string of commands piped together. This makes it difficult to read and execute the command with 'shell=False'. I was just wondering if shell=False provided some intrinsic defense against dangerous commands like 'rm -rf /'.
If the XML is specifying the command to be run, then executing subprocess.call is inherently dangerous. Perhaps you could run the script as a user with limited privileges.
Thanks for the answer. Did I understand correctly? As long as the program (first element of list, 'cat' in your example) is NOT user supplied, it is safe to use arbitrary user input in the other elements of the list.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.