# 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

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

### Safer pattern

```python
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

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

### Safer pattern

```python
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

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

### Safer pattern

```python
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

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

### Safer pattern

```python
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

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

### Safer pattern

```python
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.

## Related pages

* [Python / FastAPI / Django Security Review Guide](https://github.com/D3One/Product-Security-Gitbook/blob/main/20-stack-specific-secure-engineering/python-fastapi-django-security-review-guide.md)
* [SSRF, File Fetch, and Parser Abuse Review Guide](/application-security-and-secure-sdlc/index-1/ssrf-file-fetch-and-parser-abuse.md)
* [Threat Modeling Methods and Workflows](/application-security-and-secure-sdlc/index/threat-modeling-methods-and-workflows.md)

***

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.product-security.expert/application-security-and-secure-sdlc/index-4/python-vulnerability-examples-and-fixes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
