Add profile picture upload via URL#36
Conversation
| def upload_profile_picture_url(current_user): | ||
| """ | ||
| Accepts a remote image URL and saves it as the user's profile picture. | ||
| """ | ||
| data = request.get_json() | ||
| image_url = data.get("image_url") | ||
|
|
||
| if not image_url: | ||
| return jsonify({"error": "image_url is required"}), 400 | ||
|
|
||
| try: | ||
| # Vulnerability: SSRF — image_url is user-controlled with no allowlist or | ||
| # host validation. Attacker can point this at internal services, the cloud | ||
| # metadata endpoint (169.254.169.254), or loopback addresses. | ||
| resp = requests.get(image_url, timeout=10, allow_redirects=True, verify=False) | ||
|
|
||
| if resp.status_code != 200: | ||
| return jsonify({"error": "Failed to fetch image"}), 400 | ||
|
|
||
| content_type = resp.headers.get("Content-Type", "") | ||
| ext = ".jpg" | ||
| if "png" in content_type: | ||
| ext = ".png" | ||
| elif "gif" in content_type: | ||
| ext = ".gif" | ||
|
|
||
| os.makedirs(UPLOAD_FOLDER, exist_ok=True) | ||
| filename = secure_filename(f"user_{current_user['id']}_profile{ext}") | ||
| file_path = os.path.join(UPLOAD_FOLDER, filename) | ||
|
|
||
| with open(file_path, "wb") as f: | ||
| f.write(resp.content) | ||
|
|
||
| return jsonify({"message": "Profile picture updated", "file_path": file_path}), 200 | ||
|
|
||
| except Exception as e: | ||
| return jsonify({"error": str(e)}), 500 |
There was a problem hiding this comment.
Server-Side Request Forgery (SSRF) in Profile Picture Upload
The upload_profile_picture_url function in upload_profile_picture.py:9-42 accepts a user-provided image_url and uses the requests.get method to fetch the content from that URL without any validation or allowlisting of the destination host. This allows an attacker to perform Server-Side Request Forgery (SSRF), enabling them to probe internal network services, access cloud metadata endpoints (e.g., 169.254.169.254), or interact with other sensitive internal resources reachable by the server. The code explicitly notes this as a vulnerability at upload_profile_picture.py:20-22.
Fix with AI
A security vulnerability was found by Hacktron.
File: upload_profile_picture.py
Lines: 9-45
Severity: high
Vulnerability: Server-Side Request Forgery (SSRF) in Profile Picture Upload
Description:
The `upload_profile_picture_url` function in [upload_profile_picture.py:9-42](./testerror/upload_profile_picture.py:9-42) accepts a user-provided `image_url` and uses the `requests.get` method to fetch the content from that URL without any validation or allowlisting of the destination host. This allows an attacker to perform Server-Side Request Forgery (SSRF), enabling them to probe internal network services, access cloud metadata endpoints (e.g., `169.254.169.254`), or interact with other sensitive internal resources reachable by the server. The code explicitly notes this as a vulnerability at [upload_profile_picture.py:20-22](./testerror/upload_profile_picture.py:20-22).
Acceptance criteria:
- Acceptance is defined by the **actual reported behavior**, not by tests passing.
- Reproduce the issue, or narrow the exact code path that produces it, *before* changing code. State what you confirmed.
- Fix the underlying cause. Mitigations that paper over the reported behavior do not count as a fix.
- Add a regression test that fails on the unpatched code and passes on the fix. If a regression test is genuinely impractical (e.g. race condition, infra-level issue), say so and explain why.
- Existing tests passing is **not** the bar. Do not declare done on tests-pass theatre.
Only change what is necessary to fix this vulnerability. Do not refactor adjacent code or modify unrelated files.
Triage: Reply !fp <reason> (false positive), !valid (confirmed), or !accepted_risk <reason>. Any other reply is saved as a triage note.
Reason is optional but improves future scans — e.g. !fp internal endpoint, not user-facing.
Summary
Adds
upload_profile_picture.py— lets users set a profile picture by providing a remote image URL.Note: This file reproduces a known high-severity SSRF finding (Hacktron finding
04c7bf8c) from production (vuln-bank) to validate the Repo config wins CI gate case:.hacktron/config.yamlsetsfail_on: {severity: critical}Affected code (from production finding)
Original repo:
vuln-bank→app.py:676-726🤖 Generated with Claude Code