From b0c9bac3f339807457384cfa3596079b79899b94 Mon Sep 17 00:00:00 2001 From: Marina Ilina Date: Wed, 27 May 2026 15:36:37 +0200 Subject: [PATCH 1/2] fix(gui): mitigate CVE-2026-48710 (BadHost) auth bypass vector Use `request.scope["path"]` instead of `request.url.path` in `require_gui_user()` to prevent Host header forgery from manipulating the login redirect `returnTo` parameter. Bump starlette >= 1.0.1. Co-Authored-By: Claude Opus 4.6 --- mise.lock | 1 + pyproject.toml | 2 +- src/aignostics_foundry_core/gui/auth.py | 2 +- tests/aignostics_foundry_core/gui/gui_test.py | 4 ++-- uv.lock | 8 ++++---- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/mise.lock b/mise.lock index 9dd26fd..ab604e7 100644 --- a/mise.lock +++ b/mise.lock @@ -125,6 +125,7 @@ url_api = "https://api.github.com/repos/minamijoyo/hcledit/releases/assets/22835 checksum = "sha256:dc7de4514c6b63e9e601c640a68cab73949b9061b3c181f1e38f3e105f6fcbfb" url = "https://github.com/minamijoyo/hcledit/releases/download/v0.2.17/hcledit_0.2.17_darwin_arm64.tar.gz" url_api = "https://api.github.com/repos/minamijoyo/hcledit/releases/assets/228357402" +github_attestations = "unavailable" [tools."github:minamijoyo/hcledit"."platforms.macos-x64"] checksum = "sha256:63e122b039af7a1641c41e47f6ad40afaa1a400330c6c54086d7fde9a090bd57" diff --git a/pyproject.toml b/pyproject.toml index 92aba88..e78ab94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,7 +66,7 @@ dependencies = [ "nicegui>=3,<4", "truststore>=0.9,<1", "typer>=0.14,<1", - "starlette>=1.0.0", + "starlette>=1.0.1", ] [dependency-groups] diff --git a/src/aignostics_foundry_core/gui/auth.py b/src/aignostics_foundry_core/gui/auth.py index 8f57107..e1216b4 100644 --- a/src/aignostics_foundry_core/gui/auth.py +++ b/src/aignostics_foundry_core/gui/auth.py @@ -205,7 +205,7 @@ async def require_gui_user(request: Request, return_to: str | None = None) -> di user = await get_gui_user(request) if not user: - redirect_path = return_to or request.url.path + redirect_path = return_to or request.scope["path"] login_url = f"/auth/login?returnTo={redirect_path}" ui.navigate.to(login_url) return None diff --git a/tests/aignostics_foundry_core/gui/gui_test.py b/tests/aignostics_foundry_core/gui/gui_test.py index fa3d62d..f0784cc 100644 --- a/tests/aignostics_foundry_core/gui/gui_test.py +++ b/tests/aignostics_foundry_core/gui/gui_test.py @@ -523,7 +523,7 @@ async def test_redirects_to_login_when_no_user(self) -> None: from aignostics_foundry_core.gui.auth import require_gui_user request = MagicMock() - request.url.path = "/protected" + request.scope = {"path": "/protected"} request.app.state = MagicMock(spec=[]) # no auth_client → get_gui_user returns None navigate_mock = MagicMock() @@ -557,7 +557,7 @@ async def test_uses_return_to_override(self) -> None: from aignostics_foundry_core.gui.auth import require_gui_user request = MagicMock() - request.url.path = "/original" + request.scope = {"path": "/original"} request.app.state = MagicMock(spec=[]) # no auth_client → get_gui_user returns None navigate_mock = MagicMock() diff --git a/uv.lock b/uv.lock index ba28ee4..a129173 100644 --- a/uv.lock +++ b/uv.lock @@ -83,7 +83,7 @@ requires-dist = [ { name = "rich", specifier = ">=15,<16" }, { name = "sentry-sdk", specifier = ">=2,<3" }, { name = "sqlalchemy", extras = ["postgresql-psycopgbinary", "asyncio"], specifier = ">=2.0.31,<3" }, - { name = "starlette", specifier = ">=1.0.0" }, + { name = "starlette", specifier = ">=1.0.1" }, { name = "truststore", specifier = ">=0.9,<1" }, { name = "typer", specifier = ">=0.14,<1" }, ] @@ -3313,15 +3313,15 @@ postgresql-psycopgbinary = [ [[package]] name = "starlette" -version = "1.0.0" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/81/69/17425771797c36cded50b7fe44e850315d039f28b15901ab44839e70b593/starlette-1.0.0.tar.gz", hash = "sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149", size = 2655289, upload-time = "2026-03-22T18:29:46.779Z" } +sdist = { url = "https://files.pythonhosted.org/packages/95/66/4d20cdf39a8d6a51e663b7038e3b828ff211d3891a43a713fe7e4643f3a8/starlette-1.1.0.tar.gz", hash = "sha256:e83c7fe0ddecd8719c5b840080325aec0260acec86e9832899e377b91d65e90f", size = 2660060, upload-time = "2026-05-23T16:55:41.376Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl", hash = "sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b", size = 72651, upload-time = "2026-03-22T18:29:45.111Z" }, + { url = "https://files.pythonhosted.org/packages/93/79/920b8e0a8b20f793e8d64855095cb8febabf6175b8550b6f7a547d813891/starlette-1.1.0-py3-none-any.whl", hash = "sha256:7f0dfd38e428aad5cb6f9f667f0ca1d2d8ca3f3385dccac8305f79ec98458382", size = 72899, upload-time = "2026-05-23T16:55:39.201Z" }, ] [[package]] From 7f0ce0bb0715e60691d7d8e7af3cb76fc1504daa Mon Sep 17 00:00:00 2001 From: melifaro <1249601+melifaro@users.noreply.github.com> Date: Wed, 27 May 2026 13:37:29 +0000 Subject: [PATCH 2/2] chore: regenerate mise.lock --- mise.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/mise.lock b/mise.lock index ab604e7..9dd26fd 100644 --- a/mise.lock +++ b/mise.lock @@ -125,7 +125,6 @@ url_api = "https://api.github.com/repos/minamijoyo/hcledit/releases/assets/22835 checksum = "sha256:dc7de4514c6b63e9e601c640a68cab73949b9061b3c181f1e38f3e105f6fcbfb" url = "https://github.com/minamijoyo/hcledit/releases/download/v0.2.17/hcledit_0.2.17_darwin_arm64.tar.gz" url_api = "https://api.github.com/repos/minamijoyo/hcledit/releases/assets/228357402" -github_attestations = "unavailable" [tools."github:minamijoyo/hcledit"."platforms.macos-x64"] checksum = "sha256:63e122b039af7a1641c41e47f6ad40afaa1a400330c6c54086d7fde9a090bd57"