Identify and fix security vulnerabilities in Python code with Bandit
Everton Tenorio
Posted on September 10, 2023
Objective: Explore three security incidents in Python code identified by Bandit, a powerful security analysis tool, and learn how to fix them.
Bandit is a security analysis tool for Python source code that scans your code for known vulnerabilities and potential security threats.
Code
import requests
from flask import Flask, Response
app = Flask(__name__)
@app.route('/')
def home():
json_url = 'http://127.0.0.1:3000'
response = requests.get(json_url)
json_data = response.json()
page = []
for data in json_data:
dia_jogo = f"<h2>{data.get('diaJogo', '')}</h2>"
tabela_html = data.get('content', '')
page.append(dia_jogo)
page.append(tabela_html)
return Response(page)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
This example defines a web application using the Flask framework. When someone accesses the root ("/") of the application, it sends an HTTP request to a local server (http://127.0.0.1:3000) using the "requests" lib and retrieves JSON data as a response. It then formats this data into HTML and displays it as a web page in the user's browser, including headings (<h2>)
and tables. The application runs on "0.0.0.0" on port 5000 in debug mode when the script is executed directly.
Imagine a scenario where this code was developed locally, and after working as expected, it is now running on some server. Let's run Bandit to see if we can find anything wrong.
Bandit
pip install bandit
fut.py
, the name of the file where the example code above is located.
Run: bandit fut.py
We have the output of the command with these three incidents found:
Incident 1: Request Without Timeout
The first vulnerability identified by Bandit is the lack of a timeout in an HTTP request. In our code, the requests.get(json_url)
call does not have a specified timeout, which can lead to performance issues or blocking if the server does not respond. To prevent this, you should set a timeout for your request, as explained here.
Incident 2: Flask Debug Mode Exposure
One of the most serious issues identified by Bandit is the exposure of Flask's debug mode. In our example, setting debug=True
allows the Werkzeug debugger to be accessed externally, which could enable arbitrary code execution via HTTP requests. To fix this, make sure to disable debug mode in production environments, as discussed here.
Incident 3: Binding to All Interfaces
The last incident identified is the potential binding to all network interfaces. In this case, the code binds the application to all interfaces using host='0.0.0.0'
, which can be risky in terms of security. To fix this, you should specify the interface to which you want to bind your application, and most likely in this case, a reverse web server will be used to forward requests to the Flask application running on localhost (127.0.0.1) and the specific port. Details about this incident are discussed here.
import requests
from flask import Flask, Response
app = Flask(__name__)
@app.route('/')
def home():
json_url = 'http://127.0.0.1:3000'
response = requests.get(json_url, timeout=10)
json_data = response.json()
page = []
for data in json_data:
dia_jogo = f"<h2>{data.get('diaJogo', '')}</h2>"
tabela_html = data.get('content', '')
page.append(dia_jogo)
page.append(tabela_html)
return Response(page)
if __name__ == '__main__':
app.run()
Conclusion
Bandit will provide detailed reports on any security issues it finds in your code. You should review these reports and take appropriate actions to fix the identified vulnerabilities.
Remember that Bandit focuses on checking specific security issues in Python, such as arbitrary code execution vulnerabilities (e.g., code injection), improper secret management, and other known risks.
By addressing these three incidents identified by Bandit, you’ve learned that it’s important to always keep your code secure and up-to-date by following best security practices.
Posted on September 10, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.