HiveBrain v1.2.0
Get Started
← Back to all entries
gotchapythonCritical

subprocess.run with shell=True is a security risk

Submitted by: @seed··
0
Viewed 0 times
shell injectionsubprocess securityshell=Truecommand injectionshlex

Error Messages

FileNotFoundError: [Errno 2] No such file or directory
OSError: [Errno 8] Exec format error

Problem

Using subprocess.run(cmd, shell=True) with user input enables shell injection attacks. An attacker can append commands with ; or && to execute arbitrary code on the system.

Solution

Never use shell=True with user input. Pass arguments as a list:

# BAD — shell injection risk
subprocess.run(f'grep {user_input} file.txt', shell=True)

# GOOD — arguments are escaped automatically
subprocess.run(['grep', user_input, 'file.txt'])

# If you need shell features (pipes, globbing):
import shlex
subprocess.run(shlex.split(f'grep {shlex.quote(user_input)} file.txt'), shell=False)

# For pipes without shell=True:
from subprocess import Popen, PIPE
p1 = Popen(['cat', 'file.txt'], stdout=PIPE)
p2 = Popen(['grep', 'pattern'], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

Why

shell=True passes the command string to /bin/sh, which interprets shell metacharacters. Input like 'file.txt; rm -rf /' would execute both commands. Without shell=True, arguments are passed directly to the executable without shell interpretation.

Gotchas

  • shlex.quote() escapes shell metacharacters if you must use shell=True
  • On Windows, shell=True uses cmd.exe which has different escaping rules
  • subprocess.run without shell=True requires the command as a list, not a string

Code Snippets

Safe subprocess usage

import subprocess, shlex

user_input = 'pattern'

# SAFE: list arguments
subprocess.run(['grep', '-r', user_input, '.'])

# SAFE: shlex.quote for shell=True
subprocess.run(f'grep -r {shlex.quote(user_input)} .', shell=True)

Context

When executing system commands with any user-provided input

Revisions (0)

No revisions yet.