🎉 75% of content is free forever — Unlock Premium from $10/mo →
CW
Search courses…
💼 Servicesℹ️ About✉️ ContactView Pricing Plansfrom $10

Python Security — Protecting Your Code

Python AdvancedSecurity🟢 Free Lesson

Advertisement

Python Security — Protecting Your Code

Security is critical for any application. Python provides tools and patterns to protect against common vulnerabilities like injection attacks, data leaks, and authentication bypass.

Learning Objectives

  • Prevent SQL injection, XSS, and CSRF attacks
  • Manage secrets and credentials securely
  • Validate and sanitize all user input
  • Implement proper password hashing and authentication

SQL Injection Prevention

Never use string formatting for SQL queries:

import sqlite3

# DANGEROUS — never do this
# cursor.execute(f"SELECT * FROM users WHERE name = '{user_input}'")
# This allows: ' OR '1'='1' --

# SAFE — use parameterized queries
cursor.execute("SELECT * FROM users WHERE name = ?", (user_input,))

# With SQLAlchemy ORM (also safe)
user = session.query(User).filter(User.name == user_input).first()

Attack example:

# Attacker submits: ' OR '1'='1' --
# SQL becomes: SELECT * FROM users WHERE name = '' OR '1'='1' --'
# This returns ALL users!

Secrets Management

Never hardcode secrets in source code:

import os
from pathlib import Path

# BAD — never commit secrets
# API_KEY = "sk-1234567890"

# GOOD — use environment variables
API_KEY = os.environ.get("API_KEY")
if not API_KEY:
    raise ValueError("API_KEY environment variable not set")

# BETTER — use .env files with python-dotenv
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.environ["API_KEY"]

# BEST — use a secrets manager (AWS Secrets Manager, HashiCorp Vault)

.env file (never commit):

DATABASE_URL=postgresql://user:pass@localhost/db
API_KEY=sk-1234567890
SECRET_KEY=my-secret-key

Input Validation

Validate and sanitize all user input:

import re
from pydantic import BaseModel, validator

# Email validation
def validate_email(email: str) -> bool:
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))

# Pydantic validation (recommended)
class UserInput(BaseModel):
    name: str
    email: str
    age: int

    @validator('name')
    def name_must_be_safe(cls, v):
        if not re.match(r'^[a-zA-Z\s]{2,50}$', v):
            raise ValueError('Invalid name')
        return v

    @validator('age')
    def age_must_be_reasonable(cls, v):
        if not 0 <= v <= 150:
            raise ValueError('Invalid age')
        return v

Password Hashing

Always hash passwords before storing:

import bcrypt

# Hash a password
password = "my_secret_password".encode()
hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))

# Verify a password
if bcrypt.checkpw(password, hashed):
    print("Password matches")

# Store hashed password in database
# NEVER store plain text passwords!

Why bcrypt?

  • Automatically generates salt
  • Configurable work factor (rounds)
  • Resistant to rainbow table attacks
  • Slow by design (brute-force protection)

HTTPS and TLS

Always encrypt data in transit:

import requests

# Always use HTTPS for sensitive requests
response = requests.get("https://api.example.com/data", verify=True)

# For development with self-signed certs (NOT in production)
# response = requests.get("https://localhost:8000", verify=False)

CORS Configuration

Control who can access your API:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# Allow specific origins (NOT * in production)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://myapp.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST"],
    allow_headers=["*"],
)

Rate Limiting

Prevent abuse and DoS attacks:

from fastapi import FastAPI, Request
from slowapi import Limiter
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)
app = FastAPI()
app.state.limiter = limiter

@app.get("/api/data")
@limiter.limit("100/minute")
async def get_data(request: Request):
    return {"data": "value"}

Security Checklist

CheckAction
SQL InjectionUse parameterized queries, never f-strings
XSSEscape output, use CSP headers
CSRFUse tokens, SameSite cookies
SecretsEnvironment variables, never in code
Passwordsbcrypt/argon2 with high rounds
HTTPSAlways in production
InputValidate with Pydantic or marshmallow
Rate LimitingProtect endpoints from abuse

Common Vulnerabilities

VulnerabilityRiskPrevention
SQL InjectionData theft/modificationParameterized queries
XSSSession hijackingOutput escaping, CSP
CSRFUnauthorized actionsCSRF tokens
Weak passwordsAccount compromisebcrypt with rounds=12
Hardcoded secretsCredential leakageEnvironment variables
No rate limitingDoS attacksRate limit middleware

Key Takeaways

  1. Always use parameterized queries — never use f-strings for SQL
  2. Store secrets in environment variables, never in source code
  3. Validate and sanitize all user input — use Pydantic for validation
  4. Use bcrypt for password hashing — never store plain text passwords
  5. Always use HTTPS in production — encrypt data in transit
  6. Implement rate limiting to prevent abuse and DoS attacks

Premium Content

Python Security — Protecting Your Code

Unlock this lesson and 900+ advanced tutorials with a Premium plan.

🎯End-to-end Projects
💼Interview Prep
📜Certificates
🤝Community Access

Already a member? Log in

Need Expert Python Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement