Codiga has joined Datadog!

Read the Blog·

Interested in our Static Analysis?

Sign up
← All posts
Julien Delange Sunday, October 16, 2022

Secure Python Code: safe usage of the subprocess module

Share

AUTHOR

Julien Delange, Founder and CEO

Julien is the CEO of Codiga. Before starting Codiga, Julien was a software engineer at Twitter and Amazon Web Services.

Julien has a PhD in computer science from Universite Pierre et Marie Curie in Paris, France.

See all articles

What is the subprocess module in Python?

The subprocess module in Python creates new OS processes (think of it like a fork on steroids). The module has different methods (e.g., Popen, run) to execute new processes, get their outputs and check that they execute without any issues.

This module is often used for system administration/devops scripts, where a program needs to interact with other commands. It's convenient for automating tasks and more often more powerful than shell scripts (and Python more a more expressive language). For these reasons, the subprocess module is really popular.

Python Submodule responsibility

Why the subprocess module may be unsafe?

The subprocess module has multiple convenient features that introduce potential vulnerability. When the argument shell is set to True in its functions (such as Popen or run), the new process is executed through the shell.

When shell=True is used, the command must be formatted as if it were used in a shell. And it also means that if the command contains any user inputs, the user may inject commands to execute and compromise the system.

Say you have the following code:

import subprocess

...

subprocess.run(f"mycommand {user} {argument}", shell=True, check=True)

If a user somewhat managed to pass the value ; rm -rf / ; in the user or argument variable, this command would remove all files that belong to the user executing the command. And if the program is executed as root, it could remove all files on the system.

Such vulnerability is known as CWE-78: Improper Neutralization of Special Elements used in an OS Command. For this reason, it's really important to make sure that any method of the subprocess module is safely used.

How to safely and securely use the subprocess Python module?

The best fix is to avoid using shell=True altogether. It may be difficult to do so, especially when chaining multiple commands or when the invoked program needs the shell environment.

One remediation is to use the shlex module and its split method. The split method splits all the arguments, making sure they are quoted.

By using the shlex.split method, the fix would then be the code above would be changed to:

import subprocess
import shlex

...

subprocess.run(shlex.split(f"mycommand {user} {argument}"), shell=True, check=True)

Still, the solution with shlex is one remediation and may not work everywhere (and raising portability issues). The best solution to use safely subprocess is to avoid using shell=True.

Automatically detect unsafe use of the subprocess module

The Codiga IDE plugins and the integrations with GitHub, GitLab, or Bitbucket let you detect unsafe usage of the Python subprocess module. The Codiga static code analysis not only detects unsafe code but also suggests fixes to correct it. There is a dedicated rule to detect unsafe usage of the subprocess module.

Code Analysis Rule for Unsafe use of the subprocess module

To use this rule consistently, all you need to do is to install the integration in your IDE (for VS Code or JetBrains) or code management system and add a codiga.yml file at the root of your profile with the following content:

rulesets:
  - python-security

It will then check all your Python code against 100+ rules that detect unsafe and insecure code and suggests fixes for each of them.

More resources

Are you interested in Datadog Static Analysis?

Sign up