Skip to content

Commit

Permalink
Block /file= filepaths that could expose credentials on Windows (#7444
Browse files Browse the repository at this point in the history
)

* fix for windowss

* path

* add changeset

* changes

---------

Co-authored-by: gradio-pr-bot <[email protected]>
  • Loading branch information
abidlabs and gradio-pr-bot authored Feb 15, 2024
1 parent c88290d commit 4faf8a7
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .changeset/brown-ties-happen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"gradio": minor
---

feat:Block `/file=` filepaths that could expose credentials on Windows
6 changes: 6 additions & 0 deletions gradio/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,12 +428,18 @@ async def file(path_or_url: str, request: fastapi.Request):
return RedirectResponse(
url=path_or_url, status_code=status.HTTP_302_FOUND
)

invalid_prefixes = ["//", "file://", "ftp://", "sftp://", "smb://"]
if any(path_or_url.startswith(prefix) for prefix in invalid_prefixes):
raise HTTPException(403, f"File not allowed: {path_or_url}.")

abs_path = utils.abspath(path_or_url)

in_blocklist = any(
utils.is_in_or_equal(abs_path, blocked_path)
for blocked_path in blocks.blocked_paths
)

is_dir = abs_path.is_dir()

if in_blocklist or is_dir:
Expand Down
25 changes: 6 additions & 19 deletions test/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,17 @@ def test_asset_file_missing(self, test_client):
def test_cannot_access_files_in_working_directory(self, test_client):
response = test_client.get(r"/file=not-here.js")
assert response.status_code == 403
response = test_client.get(r"/file=subdir/.env")
assert response.status_code == 403

def test_cannot_access_directories_in_working_directory(self, test_client):
response = test_client.get(r"/file=gradio")
assert response.status_code == 403

def test_block_protocols_that_expose_windows_credentials(self, test_client):
response = test_client.get(r"/file=//11.0.225.200/share")
assert response.status_code == 403

def test_do_not_expose_existence_of_files_outside_working_directory(
self, test_client
):
Expand Down Expand Up @@ -720,25 +726,6 @@ def test_orjson_serialization():
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


def test_api_name_set_for_all_events(connect):
with gr.Blocks() as demo:
i = Textbox()
Expand Down

0 comments on commit 4faf8a7

Please sign in to comment.