Python Security: 6 Common Risks and What You Can Do About Them

Python is a high-level programming language that abstracts many details of the operating environment. This also makes it more vulnerable to certain types of attacks.

January 4, 2023

What Is Python?

Python is a high-level programming language. High-level languages abstract computer details for programmers, including memory management, pointers, processes, threads, and more. This abstraction simplifies and speeds up the coding process, improving developer productivity.

Like any programming language, Python is only as secure as the code that is written in it. Properly written Python code can be secure, but code that is not written securely can leave your application vulnerable to security risks. 

Python has a number of built-in features and libraries that can help developers write secure code, such as input validation and sanitization, and secure web frameworks such as Django and Flask. Python also has a large and active community of users and developers, which can help identify and fix potential security vulnerabilities.

This is part of a series of articles about application security.

In this article:

6 Common Python Security Vulnerabilities 

1. Injections and Arbitrary Command Execution

Injection flaws allow an attacker to deliver malicious code through an application to a backend or internal system. Injection vulnerabilities are common in Python, and come in several types such as command injection and SQL injection.

User input is passed directly to standard Python functions (system, popen) responsible for executing commands on the system. This allows an attacker to execute commands on the target system.

2. Overly Verbose Python Messages or Errors

In a development environment, it is common to see detailed debug output, to help developers identify and troubleshoot problems. However, it is important to separate the development environment from the production environment. Debugging information shown on production systems can lead to security issues. Without environmental isolation, malicious actors can gain sensitive information that can help them compromise the system.

3. Directory Traversal

This vulnerability exists due to improper sanitization of user input when accessing files. This attacker could embed files on the server via the browser. This can expose sensitive files and potentially lead to remote code execution. Directory traversal can happen when an application accesses a file but does not properly validate the path. This allows users to manipulate paths to access sensitive files such as /etc/passwd on the server.

4. Outdated Dependencies or Modules

Simply put, dependencies define functions, classes, and variables. Vulnerabilities can accidentally appear during module creation. Therefore, developers should frequently update these dependencies to patch vulnerabilities. Components with outdated dependencies or vulnerabilities pose a threat to your organization.

5. Insecure Usage of mktemp() Function

Most Python programs create temporary files. You can generate arbitrary filenames using the mktemp() function. However, this feature is not completely secure. Because the name is randomly generated, you may end up with another file with the same name. Doing so will overwrite other previously saved files and may result in loss of information. Attackers can manipulate this behavior to obtain sensitive data from temporary files.

6. Exploited and Malicious Packages

Packaging is very convenient and saves time for developers. Packages can be easily installed using Pip. Benefits include a smaller code base, simpler application design, and better performance.

Most Python packages are published on PyPI, which serves as a code repository for Python packages and do not undergo any form of security review or scrutiny.

This means that anyone with malicious intent can easily build a package containing malicious code and publish it on PyPI, or publish a package with a similar name to a popular package. 

Carefully check all Python packages you install and import to ensure they are safe. You can also use security tools to scan Python dependencies and filter out exploited packages.

Python Security Best Practices

Review Your Dependency Licenses

When using an open source project, it’s important to understand how that project is licensed. Open source projects are free to use, but terms of use may apply. These terms usually cover how the software is to be used, whether changes must be made to the released software, and other similar requirements. Familiarize yourself with the open source licenses your project uses.

If your project is covered by a license that is restrictive (copyleft licenses like GPL or SSPL), you must either comply with the terms of the license or stop using the project. Also, if you change the code without permission, you may be violating copyright laws.

Scan and fix licensing and vulnerability issues in your project dependencies to ensure that your project is sustainable and not exposed to unnecessary Python security and legal risks.

Check for Vulnerable Dependencies

Python applications can depend on many Python libraries. Any of these might have security weaknesses, so you need to make sure you are using updated versions. There are many services that proactively scan for codes and open pull requests with suggested updates. 

Sanitize Your Code with Linters 

For Python, there is a document called PEP (Python Enhancement Proposal). This document provides a long list of rules to improve Python code, making it more readable and consistent. Unfortunately, even experienced programmers can have a hard time remembering all the rules written in the PEP. That’s why Python linters were created.

A linter is a program that provides code quality suggestions by displaying warnings and errors. You can detect errors in your Python code, check for invalid code patterns, and spot unusual elements. Python linters have many advantages, including eliminating errors in code, making code easy for all Python programmers to read, removing unnecessary code, and keeping code clean and uncomplicated.