ded
ded

Reputation: 430

python using popen without shell, or assert to increase safety

Using subprocess.popen to call an external program within my script. I have been unable to get it to work without shell=True, and have added an assert statement to make things less dangerous (I think).

Relevant code lines:

import subprocess
import re
import argparse

parser = argparse.ArgumentParser(description="options")
parser.add_argument("-p", "--prefix", help="prefix for output files")
args = parser.parse_args()

assert re.match("^[a-zA-Z0-9_]+$", args.prefix), "non-alphanumeric characters found"

command = "my_external_program -t type -f %s -m 1 -M 1 -N 0 -H -p 16" % args.prefix
external_stacks_call = subprocess.Popen(command, shell=True, stdout=open(args.prefix + ".log.txt", "a"), stderr=open(args.prefix + ".log.txt", "a"))
external_stacks_call.wait()

questions are as follows:

  1. is the assert statment safe enough to avoid mischief/problems by others, or other unanticipated problems?
    1. for example someone entering a prefix of "stuff && rm -rf /"
  2. what is the best way to not call this same string without the shell=True option?

I have looked at several pages here and elsewhere about the dangers of the shell=True option, and the dangers of shell=True, but I have not found a good source of how to avoid using it for an external program

Upvotes: 1

Views: 372

Answers (1)

Ryan Haining
Ryan Haining

Reputation: 36872

shell=True will escape the spaces, however you can also provide a list of args for the command line

command = ["my_external_program", "-t", "type", "-f", str(args.prefix), 
           "-m", "1", "-M", "1", "-N", "0", "-H", "-p", "16"]

This will allow the module to interface with the shell correctly, more safely

Without shell=True special characters will be escaped, so the equivalent of your original command would be

$ my_external_program\ -t\ type\ -f

etc.

This is an advantage because the shell can then escape all kinds of special characters in the same way

Upvotes: 2

Related Questions