Writing Secure Python Code

Loading

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 of http://).
  • 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

Leave a Reply

Your email address will not be published. Required fields are marked *