PS Product SecurityKnowledge Base

๐Ÿ Python Vulnerability Examples and Fixes

Use this page when: reviewing Flask, Django, FastAPI, worker processes, CLI helpers, internal automation, or data-handling code that looks harmless but sits on production trust boundaries.

How to read these examples

  • Vulnerable snippet shows the unsafe habit.
  • Safer pattern shows the direction you want in production code.
  • Why it matters ties the defect to attacker value and business impact.
  • Review cue is phrased so it can become a pull-request comment or checklist item.

Example 1 โ€” SQL injection with string formatting

Vulnerable snippet

username = request.args["username"]
query = f"SELECT id, role FROM users WHERE username = '{username}'"
row = conn.execute(query).fetchone()

Safer pattern

username = request.args["username"]
row = conn.execute(
    "SELECT id, role FROM users WHERE username = ?",
    (username,),
).fetchone()

Why it matters

  • F-strings and % formatting blur data and query structure, which is exactly what injection needs.

Business impact

  • Account discovery, data leaks, auth bypass, and possible write/delete operations depending on DB permissions.

Review cue

  • Parameterize values every time; never build SQL with f-strings, %, or .format().

Example 2 โ€” Unsafe deserialization with pickle

Vulnerable snippet

payload = request.cookies.get("prefs")
settings = pickle.loads(base64.b64decode(payload))

Safer pattern

payload = request.cookies.get("prefs", "{}")
settings = json.loads(payload)
allowed = {"theme", "page_size"}
settings = {k: v for k, v in settings.items() if k in allowed}

Why it matters

  • pickle.loads() can reconstruct attacker-controlled objects and trigger arbitrary code execution paths.

Business impact

  • Remote code execution in app or worker processes, secret theft, queue poisoning, and persistence opportunities.

Review cue

  • Never deserialize untrusted bytes with pickle. Prefer JSON or another constrained format with explicit schemas.

Example 3 โ€” Path traversal in file retrieval

Vulnerable snippet

filename = request.args["name"]
with open(f"/srv/reports/{filename}", "rb") as fh:
    return fh.read()

Safer pattern

from pathlib import Path

base = Path("/srv/reports").resolve()
name = request.args["name"]
path = (base / name).resolve()

if base not in path.parents and path != base:
    raise PermissionError("invalid path")

with open(path, "rb") as fh:
    return fh.read()

Why it matters

  • User-controlled file names can escape the intended directory with ../ tricks or platform-specific path variants.

Business impact

  • Exposure of secrets, configuration, source code, SSH keys, tokens, or internal documents.

Review cue

  • Resolve against a fixed base directory and prove the final path still lives inside it.

Example 4 โ€” SSRF through unrestricted URL fetch

Vulnerable snippet

url = request.json["url"]
r = requests.get(url, timeout=5)
return r.text

Safer pattern

from urllib.parse import urlparse

ALLOWED_HOSTS = {"status.example.com", "images.example-cdn.com"}
url = request.json["url"]
parsed = urlparse(url)

if parsed.scheme != "https" or parsed.hostname not in ALLOWED_HOSTS:
    raise PermissionError("destination not allowed")

r = requests.get(url, timeout=5, allow_redirects=False)
return r.text

Why it matters

  • Blind outbound fetch lets attackers pivot into metadata services, internal APIs, admin panels, or egress-trusted systems.

Business impact

  • Credential theft, cloud compromise, internal reconnaissance, or abuse of third-party integrations.

Review cue

  • Any user-influenced outbound request needs destination allowlists, redirect control, and private-address blocking.

Example 5 โ€” Command injection via subprocess shell=True

Vulnerable snippet

term = request.args["term"]
subprocess.run(f"grep -R {term} /srv/docs", shell=True, check=True)

Safer pattern

term = request.args["term"]
if not re.fullmatch(r"[a-zA-Z0-9._ -]{1,40}", term):
    raise ValueError("bad search term")

subprocess.run(["grep", "-R", "--", term, "/srv/docs"], check=True)

Why it matters

  • A shell interprets metacharacters, pipes, subshells, and injected options, which turns a search field into code execution.

Business impact

  • Host compromise, secret exposure, tampering with logs or artifacts, and operational outage.

Review cue

  • Prefer argument arrays over shells, validate inputs, and use -- when a tool may parse user data as flags.

Author attribution: Ivan Piskunov, 2026 - Educational and defensive-engineering use.