diff --git a/CHANGELOG.md b/CHANGELOG.md index ff71c8e3015d0..cf18c61943428 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ ## Breaking Changes: -No changes to highlight. +- The `/file=` route no longer allows accessing dotfiles or files in "dot directories" by [@akx](https://github.com/akx) in [PR 4303](https://github.com/gradio-app/gradio/pull/4303) # 3.32.0 diff --git a/gradio/routes.py b/gradio/routes.py index 753c55c7c634b..055db04247185 100644 --- a/gradio/routes.py +++ b/gradio/routes.py @@ -326,7 +326,7 @@ async def file(path_or_url: str, request: fastapi.Request): utils.is_in_or_equal(abs_path, blocked_path) for blocked_path in blocks.blocked_paths ) - if in_blocklist: + if in_blocklist or any(part.startswith(".") for part in abs_path.parts): raise HTTPException(403, f"File not allowed: {path_or_url}.") in_app_dir = utils.abspath(app.cwd) in abs_path.parents diff --git a/test/test_routes.py b/test/test_routes.py index 918b459d7d97a..9729a9aa40673 100644 --- a/test/test_routes.py +++ b/test/test_routes.py @@ -3,6 +3,7 @@ import os import sys import tempfile +from contextlib import closing from pathlib import Path from unittest.mock import patch @@ -645,3 +646,22 @@ def test_orjson_serialization(): response = test_client.get("/") assert response.status_code == 200 demo.close() + + +def test_file_route_does_not_allow_dot_paths(tmp_path): + dot_file = tmp_path / ".env" + dot_file.write_text("secret=1234") + subdir = tmp_path / "subdir" + subdir.mkdir() + sub_dot_file = subdir / ".env" + sub_dot_file.write_text("secret=1234") + secret_sub_dir = tmp_path / ".versioncontrol" + secret_sub_dir.mkdir() + secret_sub_dir_regular_file = secret_sub_dir / "settings" + secret_sub_dir_regular_file.write_text("token = 8") + with closing(gr.Interface(lambda s: s.name, gr.File(), gr.File())) as io: + app, _, _ = io.launch(prevent_thread_lock=True) + client = TestClient(app) + assert client.get("/file=.env").status_code == 403 + assert client.get("/file=subdir/.env").status_code == 403 + assert client.get("/file=.versioncontrol/settings").status_code == 403