Writing secure Python code is essential to protect applications from vulnerabilities like SQL injection, cross-site scripting (XSS), insecure authentication, and data leaks. This guide covers best practices to enhance security in Python applications.
1. Avoid Hardcoded Credentials
Hardcoded API keys, passwords, and database credentials make applications vulnerable.
Insecure Code:
db_password = "mypassword123" # ❌ Bad practice
Secure Solution:
Use environment variables instead.
import os
db_password = os.getenv("DB_PASSWORD")
Store credentials in .env
files or secrets managers.
2. Use Secure Password Hashing
Never store passwords in plain text.
Insecure Code:
users = {"admin": "mypassword"} # ❌ Plaintext storage
Secure Solution:
Use bcrypt for hashing passwords.
import bcrypt
password = b"mypassword"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
if bcrypt.checkpw(password, hashed):
print("Login successful")
Never store or transmit plaintext passwords.
3. Prevent SQL Injection
Using raw SQL queries makes applications vulnerable to SQL Injection.
Insecure Code:
import sqlite3
conn = sqlite3.connect("users.db")
cursor = conn.cursor()
username = input("Enter username: ")
query = f"SELECT * FROM users WHERE username = '{username}'" # ❌ Vulnerable
cursor.execute(query)
Secure Solution:
Use parameterized queries.
query = "SELECT * FROM users WHERE username = ?"
cursor.execute(query, (username,))
Prevents attackers from injecting malicious SQL commands.
4. Sanitize User Input to Prevent XSS
Cross-Site Scripting (XSS) occurs when user input is executed as code.
Insecure Code:
from flask import request
user_input = request.args.get("name")
html_response = f"<h1>Welcome {user_input}</h1>" # ❌ Dangerous
Secure Solution:
Use HTML escaping to prevent script execution.
pythonCopyEditfrom markupsafe import escape
html_response = f"<h1>Welcome {escape(user_input)}</h1>"
Prevents JavaScript execution in user input.
5. Validate and Sanitize Input
Unvalidated input can lead to command injection, buffer overflow, and security breaches.
Insecure Code:
import os
filename = input("Enter filename: ")
os.system(f"rm {filename}") # ❌ Allows command injection
Secure Solution:
Use strict validation and whitelisting.
import re
if not re.match(r"^[a-zA-Z0-9_.-]+$", filename):
raise ValueError("Invalid filename")
Prevents attackers from executing arbitrary commands.
6. Use Secure Authentication Mechanisms
Insecure Code:
pythonCopyEditif username == "admin" and password == "password123": # ❌ Hardcoded credentials
print("Access granted")
Secure Solution:
Use OAuth, JWT, or session-based authentication.
from flask import Flask, session
app = Flask(__name__)
app.secret_key = os.getenv("SECRET_KEY") # Use a strong secret key
@app.route("/login")
def login():
session["user"] = "admin" # Secure session handling
Avoid hardcoded credentials and use secure authentication methods.
7. Secure API Endpoints
Insecure Code:
@app.route("/delete_user")
def delete_user():
user_id = request.args.get("id")
os.system(f"rm -rf /users/{user_id}") # ❌ Arbitrary file deletion
Secure Solution:
Use authentication and role-based access control (RBAC).
from flask import request, abort
def delete_user():
if not user_is_admin():
abort(403) # Forbidden access
Restrict access based on user roles.
8. Use HTTPS for Secure Communication
Using HTTP exposes data to man-in-the-middle (MITM) attacks.
Secure Solution:
- Always use HTTPS (
https://
instead ofhttp://
). - Use TLS certificates (Let’s Encrypt, AWS ACM, etc.).
- Set security headers in responses.
from flask import Flask, Response
app = Flask(__name__)
@app.after_request
def set_secure_headers(response: Response):
response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
return response
Prevents data interception and MITM attacks.
9. Secure File Handling
Insecure Code:
file = request.files["file"]
file.save(f"/uploads/{file.filename}") # ❌ Vulnerable to path traversal
Secure Solution:
Use safe file extensions and unique filenames.
import werkzeug
filename = werkzeug.utils.secure_filename(file.filename)
file.save(f"/uploads/{filename}")
Prevents attackers from overwriting files or accessing sensitive directories.
10. Use Security Headers in Web Applications
Set security headers to prevent clickjacking, XSS, and data leaks.
@app.after_request
def set_headers(response):
response.headers["Content-Security-Policy"] = "default-src 'self'"
response.headers["X-Frame-Options"] = "DENY"
response.headers["X-XSS-Protection"] = "1; mode=block"
return response
Enhances browser security against common attacks.
Best Practices for Secure Python Code
✔ Keep dependencies updated (pip list --outdated
)
✔ Use virtual environments (venv
or pipenv
)
✔ Enable logging & monitoring for security events
✔ Restrict file and database permissions
✔ Follow OWASP security guidelines