Skip to content

Dangerous Python Functions

Originally:updated Feb 21, 2026

Updated in 2026 with Python 3 examples and current links.

Certain Python functions are dangerous if used carelessly. Python’s documentation typically flags the risks but rarely illustrates them well.

This post covers a few categories of dangerous functions and safer alternatives. If you spot these in the wild, pay close attention.

Dangerous Python Functions *Illustration by Carissa Sandoval*

The Command Injection Series

The first group of dangerous Python functions revolve around trusting user-provided input and piping it into a shell.

Why they’re useful

Sometimes you need to call a command-line application, and Python’s subprocess.call() with shell=True makes that convenient.

os.system() and os.popen() have been deprecated in favor of the subprocess module. They have a simple API and they’ve been around for a while so you may run into them in older applications.

Why they’re dangerous

shell=True (and the similar tools in os) lets someone craft input that issues different commands than the ones you intended.

A dangerous example

Let’s say we want to write a function to transcode a user-specified video file into a different format. We ask the user where to find the file on disk and then run it through ffmpeg to transcode it. What could go wrong?

import subprocess

def transcode_file():
    filename = input('Please provide the path for the file to transcode: ')
    command = 'ffmpeg -i "{source}" output_file.mpg'.format(source=filename)
    subprocess.call(command, shell=True)  # a bad idea!

What if someone provides a file with a name like "; rm -rf /? If the host machine runs the Python process as a privileged user, that could delete all of the files on the machine. That’s bad.

What to use instead

subprocess with shell=False. It protects you against most of the risk associated with piping commands to the shell. If you go this route, shlex.split() makes it easier to prepare the command (and is what the Python docs recommend).

sh - Useful for issuing commands to other applications. I had some trouble issuing complex commands through sh before because of the way it quotes variables. That said, if it works for your use case, then go for it!

If you must use them…

Escape your variables! Use shlex.quote() to properly escape shell arguments.

Additional references

Code Injection - exec, eval

The second group of dangerous functions relate to taking input and interpreting it as Python code.

Why they’re useful

exec() and eval() take strings and turn them into executable code. They can be useful, especially if you are the one who controls the input. As one example, I’ve used eval before to evaluate a large dict-like string into a dictionary.

Why they’re dangerous

eval() and exec() will execute whatever we feed them. A malicious string can erase your data, expose your secret keys, or dump your database.

A dangerous example

Related to the previous example, suppose you’re evaling a string that looks like this: "os.system('rm -rf /') # dangerous!". It, too, could erase all your files.

What to use instead

It depends on what you’re doing. eval and exec serve many purposes, so there’s no single replacement.

If you’re evaluating a string that contains a Python literal (a dict, list, string, number, etc.), use ast.literal_eval(). It parses the expression without executing arbitrary code.

If you’re using them to perform serialization / deserialization, it would probably be better to use another format, such as JSON, which can be loaded with the json module.

If you must use them…

Again, escape your input. You can also disable the built-ins to make it harder to craft malicious input, which Ned Batchelder covers in Eval really is dangerous.

Additional references

Next time…

We’ve covered ways in which user input can pose serious risks to Python applications. In the next part of this series, we’ll discuss issues related to deserializing data, loading yaml configurations, information leakage, and more.

Thanks to Zach Schipono and Carissa Sandoval for reviewing drafts of this.


Previous Post
Dangerous Python Functions, Part 2
Next Post
The Sunglasses Scam