Data becomes untrusted when it crosses from a user, file, network response, environment, database, queue, or external command into the program. Validation, safe APIs, output encoding, authorization, and resource limits solve different parts of that boundary.
After this lesson, you can choose secrets instead of random for tokens, pass subprocess arguments without a shell, reject unsafe deserialization, constrain paths to an owned directory, and keep credentials out of source and diagnostic output.
Parse external values into a narrow internal type early. Check allowed shape, length, range, and relationships; do not treat type conversion alone as validation. Reject unexpected fields when silently accepting them would hide a client mistake.
def parse_limit(raw: str) -> int:
try:
limit = int(raw)
except ValueError as exc:
raise ValueError("limit must be an integer") from exc
if not 1 <= limit <= 100:
raise ValueError("limit must be between 1 and 100")
return limit
print(parse_limit("20"))
20
The random module is intended for simulation, sampling, and reproducible pseudo-random sequences. Use secrets for password-reset tokens, session-like identifiers, and other values an attacker must not predict.
import secrets
token = secrets.token_urlsafe(32)
print(len(token) >= 32)
True
The token itself changes on every run and should be stored or transmitted only through the intended protected workflow.
subprocess does not invoke a shell by default. Pass an argument list and keep shell=False for ordinary programs so spaces and metacharacters remain data instead of command syntax.
import subprocess
result = subprocess.run(
["git", "status", "--short"],
check=True,
capture_output=True,
text=True,
timeout=10,
)
print(result.returncode)
Choose the executable and permitted options in application code; do not accept an arbitrary command list from a request.
pickle can execute code while loading and must never consume untrusted or tampered data. Use JSON for simple external data, validate the decoded structure, and use a purpose-built safe format when JSON cannot represent the domain.
Resolve the requested path beneath a fixed storage root and reject paths that escape it. Prefer mapping public identifiers to stored paths rather than accepting filesystem fragments directly.
from pathlib import Path
root = Path("reports").resolve()
candidate = (root / "weekly.csv").resolve()
if not candidate.is_relative_to(root):
raise ValueError("report path escapes storage root")
print(candidate.name)
weekly.csv
0 of 2 checked
Try this next
0 of 2 completed
Explore 500+ free tutorials across 20+ languages and frameworks.