From 01dca87bb81848d72919c6e6966a3680abfe3f0a Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Wed, 1 Apr 2026 17:47:55 +0200 Subject: [PATCH 1/3] fix: Bypass API Key validation for static bundle assets --- tools/server/server-http.cpp | 13 ++++++++++++- tools/server/tests/unit/test_security.py | 10 ++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/tools/server/server-http.cpp b/tools/server/server-http.cpp index f52240b106a3..e9991fd93e5c 100644 --- a/tools/server/server-http.cpp +++ b/tools/server/server-http.cpp @@ -151,11 +151,22 @@ bool server_http_context::init(const common_params & params) { return true; } - // If path is public or is static file, skip validation + // If path is public, skip validation if (public_endpoints.find(req.path) != public_endpoints.end() || req.path == "/") { return true; } + // Skip validation for web UI static assets (they don't require API key) + { + static const std::unordered_set static_assets = { + "/bundle.js", "/bundle.css", "/index.html", + }; + + if (static_assets.find(req.path) != static_assets.end()) { + return true; + } + } + // Check for API key in the Authorization header std::string req_api_key = req.get_header_value("Authorization"); if (req_api_key.empty()) { diff --git a/tools/server/tests/unit/test_security.py b/tools/server/tests/unit/test_security.py index 8c38b89d535e..aab3b101fd2c 100644 --- a/tools/server/tests/unit/test_security.py +++ b/tools/server/tests/unit/test_security.py @@ -22,6 +22,16 @@ def test_access_public_endpoint(endpoint: str): assert "error" not in res.body +@pytest.mark.parametrize("endpoint", ["/", "/bundle.js", "/bundle.css"]) +def test_access_static_assets_without_api_key(endpoint: str): + """Static web UI assets should not require API key authentication (issue #21229)""" + global server + server.start() + res = server.make_request("GET", endpoint) + assert res.status_code == 200 + assert "error" not in res.body + + @pytest.mark.parametrize("api_key", [None, "invalid-key"]) def test_incorrect_api_key(api_key: str): global server From 7dd27a77389c3941b41c814fcf5e8b0b1cbd7833 Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Wed, 1 Apr 2026 18:07:11 +0200 Subject: [PATCH 2/3] refactor: All bypassed routes in `public_endpoints` --- tools/server/server-http.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/tools/server/server-http.cpp b/tools/server/server-http.cpp index e9991fd93e5c..be2af26223da 100644 --- a/tools/server/server-http.cpp +++ b/tools/server/server-http.cpp @@ -143,7 +143,11 @@ bool server_http_context::init(const common_params & params) { "/v1/health", "/models", "/v1/models", - "/api/tags" + "/api/tags", + "/", + "/index.html", + "/bundle.js", + "/bundle.css", }; // If API key is not set, skip validation @@ -151,22 +155,11 @@ bool server_http_context::init(const common_params & params) { return true; } - // If path is public, skip validation - if (public_endpoints.find(req.path) != public_endpoints.end() || req.path == "/") { + // If path is public or static file, skip validation + if (public_endpoints.find(req.path) != public_endpoints.end()) { return true; } - // Skip validation for web UI static assets (they don't require API key) - { - static const std::unordered_set static_assets = { - "/bundle.js", "/bundle.css", "/index.html", - }; - - if (static_assets.find(req.path) != static_assets.end()) { - return true; - } - } - // Check for API key in the Authorization header std::string req_api_key = req.get_header_value("Authorization"); if (req_api_key.empty()) { From 976b772bf25db757e8bdcb0a6d4dd4152f52349c Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Wed, 1 Apr 2026 18:34:16 +0200 Subject: [PATCH 3/3] test: Update static assets API Key test --- tools/server/tests/unit/test_security.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/server/tests/unit/test_security.py b/tools/server/tests/unit/test_security.py index aab3b101fd2c..bb22095f125c 100644 --- a/tools/server/tests/unit/test_security.py +++ b/tools/server/tests/unit/test_security.py @@ -22,14 +22,13 @@ def test_access_public_endpoint(endpoint: str): assert "error" not in res.body -@pytest.mark.parametrize("endpoint", ["/", "/bundle.js", "/bundle.css"]) -def test_access_static_assets_without_api_key(endpoint: str): +def test_access_static_assets_without_api_key(): """Static web UI assets should not require API key authentication (issue #21229)""" global server server.start() - res = server.make_request("GET", endpoint) - assert res.status_code == 200 - assert "error" not in res.body + for path in ["/", "/bundle.js", "/bundle.css"]: + res = server.make_request("GET", path) + assert res.status_code == 200, f"Expected 200 for {path}, got {res.status_code}" @pytest.mark.parametrize("api_key", [None, "invalid-key"])