Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Python3 shlex.quote() safe?

I execute some code in shell using

subprocess.Popen('echo '+user_string+' | pipe to some string manipulation tools',
    shell=True)

where user_string is from an untrusted source.

Is it safe enough to use shlex.quote() for escaping the input?

like image 574
Nisba Avatar asked Sep 18 '25 07:09

Nisba


1 Answers

I'm necromancing this because it's the top Google hit for "is shlex.quote() safe", and while the accepted answer seems correct, there's a lot of pitfalls to point out.

shlex.quote() escapes the shell's parsing, but it does not escape the argument parser of the command you're calling, and some additional tool-specific escaping needs to be done manually, especially if your string starts with a dash (-).

Most (but not all) tools accept -- as an argument, and anything afterward is interpreted as verbatim. You can prepend "-- " if the string starts with "-". Example: rm -- --help removes the file called --help.

When dealing with file names, you can prepend "./" if the string starts with "-": rm ./--help.

In the case of your example with echo, neither escape is sufficient: When attempting to echo the string -e, echo -- -e gives the wrong result, you'll need something like echo -e \x2de. This demonstrates that there's no universal bulletproof way to escape program arguments.

The safest route is to bypass the shell by avoiding shell=True or os.system() if the string involves any user-supplied data.

In your case, set stdin=subprocess.PIPE and pass the user_string as an argument to communicate(). Then you can even leave your original invocation as-is with shell=True:

subprocess.Popen(
    'pipe to some string manipulation tools',
    shell=True,
    stdin=subprocess.PIPE
).communicate(user_input_string.encode())
like image 61
mic_e Avatar answered Sep 22 '25 05:09

mic_e



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!