Day 48 of 50 Days of Python: Python Security Best Practices
Part of Week 7: Python In Production
Your code now builds, tests, ships, and even provisions cloud infrastructure. But is it safe?
A single leaked secret or vulnerable dependency can undo weeks of engineering. In today’s newsletter, we’ll harden your Python stack, from source‑code to runtime, so attacks are mitigated and random auditors can give you the sign off.
Why Does Security Matter?
→ Supply‑chain threats – Typosquatted packages or compromised libraries slip malicious code into your pipeline.
→ Secrets leakage – Hard‑coded API keys end up in Git history and public repos.
→ Injection bugs – Unvalidated inputs reach shell, SQL, or template engines.
→ Privilege escalation – Containers run as root, converting a minor vulnerability into total host compromise.
→ Compliance – GDPR, SOC 2, HIPAA all mandate controls and audit trails.
Key Concepts
Principle of Least Privilege – Grant the minimum rights needed. No root, or wide IAM roles. Which can be difficult to enforce but is a necessary “evil”.
Dependency Pinning & Hashes – Lock exact package versions + SHA‑256 to block malicious upgrades.
Static Analysis – Detect risky code patterns before runtime (e.g.,
eval
, pickle, hard‑coded creds).Runtime Hardening – Use read‑only file systems.
Secret Management – Store keys in vaults (AWS Secrets Manager, Azure Key Vault) and inject via environment variables, never in code.
Input Sanitisation – Validate & escape user data for SQL, shell, HTML, JSON.
Transport Security – Enforce HTTPS/TLS, verify certificates, pin hosts when possible.
Audit & Monitoring – Centralise logs, enable MFA on package registries, and set up alerting on anomalous behaviour.
Hands On: Harden a Small FastAPI Service
Static Scan with Bandit
pip install bandit bandit -r src/ # high‑severity issues only: -lll
Dependency Audit with pip‑audit
pip install pip-audit pip install -r requirements.txt --no-deps pip-audit --require-hashes # fails build on known CVEs
Secret Detection in CI - Add truffleHog to GitHub Actions
- uses: trufflesecurity/trufflehog@v4 with: scanWhenModified: true
Runtime Hardening Dockerfile (snippet)
FROM python:3.11-slim WORKDIR /app RUN adduser --disabled-password --uid 1001 app COPY requirements.txt . RUN pip install --no-cache-dir --require-hashes -r requirements.txt COPY src/ src/ USER app # drop root ENTRYPOINT ["uvicorn", "src.app:create_app", "--host=0.0.0.0", "--port=8000"]
Input Validation with pydantic (FastAPI)
from pydantic import BaseModel, Field, PositiveFloat class PredictIn(BaseModel): rooms: PositiveFloat = Field(..., lt=100) households: PositiveFloat
Any invalid or extreme values are rejected automatically with
422
.
TL;DR
Scan: Bandit + pip‑audit in CI catches risky code and vulnerable packages.
Protect: Store secrets in a vault, mount as env vars, run containers as non‑root.
Validate: Enforce schemas (pydantic) to block injections early.
Lock: Pin versions & hashes; review dependency updates just like code.
Monitor: Centralised logs and MFA on critical accounts.
Next Up: Day 49 - Logging and Debugging Best Practices.
I’ll take you through logging and efficient debugging techniques. Which are backbones of production ready pipelines and code.
See you for the next one and as always… Happy coding!