Skip to content

Commit

Permalink
Merge pull request from GHSA-fvcq-4x64-hqxr
Browse files Browse the repository at this point in the history
Escape invalid host when displayed in html
  • Loading branch information
manics authored Jun 11, 2024
2 parents e8a8c09 + 2fa8c26 commit 7abc9dc
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 13 deletions.
5 changes: 4 additions & 1 deletion docs/source/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

## 4.2

### v4.2.0 - 2024-06-DD
### v4.2.0 - 2024-06-11

This release includes an important security patch for
[CVE-2024-35225 ](https://github.com/jupyterhub/jupyter-server-proxy/security/advisories/GHSA-fvcq-4x64-hqxr).

([full changelog](https://github.com/jupyterhub/jupyter-server-proxy/compare/v4.1.2...v4.2.0))

Expand Down
18 changes: 6 additions & 12 deletions jupyter_server_proxy/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,14 +323,11 @@ async def proxy(self, host, port, proxied_path):
"""

if not self._check_host_allowlist(host):
self.set_status(403)
self.write(
"Host '{host}' is not allowed. "
"See https://jupyter-server-proxy.readthedocs.io/en/latest/arbitrary-ports-hosts.html for info.".format(
host=host
)
raise web.HTTPError(
403,
f"Host '{host}' is not allowed. "
"See https://jupyter-server-proxy.readthedocs.io/en/latest/arbitrary-ports-hosts.html for info.",
)
return

# Remove hop-by-hop headers that don't necessarily apply to the request we are making
# to the backend. See https://github.com/jupyterhub/jupyter-server-proxy/pull/328
Expand Down Expand Up @@ -391,9 +388,7 @@ async def proxy(self, host, port, proxied_path):
# Ref: https://www.tornadoweb.org/en/stable/httpclient.html#tornado.httpclient.AsyncHTTPClient.fetch
if err.code == 599:
self._record_activity()
self.set_status(599)
self.write(str(err))
return
raise web.HTTPError(599, str(err))
else:
raise

Expand All @@ -402,8 +397,7 @@ async def proxy(self, host, port, proxied_path):

# For all non http errors...
if response.error and type(response.error) is not httpclient.HTTPError:
self.set_status(500)
self.write(str(response.error))
raise web.HTTPError(500, str(response.error))
else:
# Represent the original response as a RewritableResponse object.
original_response = RewritableResponse(orig_response=response)
Expand Down
11 changes: 11 additions & 0 deletions tests/test_proxies.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,17 @@ def test_server_proxy_host_absolute(a_server_port_and_token: Tuple[int, str]) ->
assert "X-Proxycontextpath" not in s


@pytest.mark.parametrize("absolute", ["", "/absolute"])
def test_server_proxy_host_invalid(
a_server_port_and_token: Tuple[int, str], absolute: str
) -> None:
PORT, TOKEN = a_server_port_and_token
r = request_get(PORT, f"/proxy{absolute}/<invalid>:54321/", TOKEN)
assert r.code == 403
s = r.read().decode("ascii")
assert "Host &#39;&lt;invalid&gt;&#39; is not allowed." in s


def test_server_proxy_port_non_service_rewrite_response(
a_server_port_and_token: Tuple[int, str]
) -> None:
Expand Down

0 comments on commit 7abc9dc

Please sign in to comment.