mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-11 20:13:02 +00:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5980ff1011 | ||
![]() |
2e8781c35b | ||
![]() |
3f1332e38f | ||
![]() |
db851cd230 | ||
![]() |
8c8e26802a | ||
![]() |
6a4900c468 | ||
![]() |
efbb692540 | ||
![]() |
244ab813fe |
@@ -9,6 +9,14 @@ command line for details.
|
|||||||
|
|
||||||
## 0.9
|
## 0.9
|
||||||
|
|
||||||
|
### [0.9.6] 2019-04-01
|
||||||
|
|
||||||
|
JupyterHub 0.9.6 is a security release.
|
||||||
|
|
||||||
|
- Fixes an Open Redirect vulnerability (CVE-2019-10255).
|
||||||
|
|
||||||
|
JupyterHub 0.9.5 included a partial fix for this issue.
|
||||||
|
|
||||||
### [0.9.4] 2018-09-24
|
### [0.9.4] 2018-09-24
|
||||||
|
|
||||||
JupyterHub 0.9.4 is a small bugfix release.
|
JupyterHub 0.9.4 is a small bugfix release.
|
||||||
@@ -426,7 +434,8 @@ Fix removal of `/login` page in 0.4.0, breaking some OAuth providers.
|
|||||||
First preview release
|
First preview release
|
||||||
|
|
||||||
|
|
||||||
[Unreleased]: https://github.com/jupyterhub/jupyterhub/compare/0.9.4...HEAD
|
[Unreleased]: https://github.com/jupyterhub/jupyterhub/compare/0.9.6...HEAD
|
||||||
|
[0.9.6]: https://github.com/jupyterhub/jupyterhub/compare/0.9.4...0.9.6
|
||||||
[0.9.4]: https://github.com/jupyterhub/jupyterhub/compare/0.9.3...0.9.4
|
[0.9.4]: https://github.com/jupyterhub/jupyterhub/compare/0.9.3...0.9.4
|
||||||
[0.9.3]: https://github.com/jupyterhub/jupyterhub/compare/0.9.2...0.9.3
|
[0.9.3]: https://github.com/jupyterhub/jupyterhub/compare/0.9.2...0.9.3
|
||||||
[0.9.2]: https://github.com/jupyterhub/jupyterhub/compare/0.9.1...0.9.2
|
[0.9.2]: https://github.com/jupyterhub/jupyterhub/compare/0.9.1...0.9.2
|
||||||
|
@@ -12,8 +12,11 @@ function get_hub_version() {
|
|||||||
split=( ${hub_xyz//./ } )
|
split=( ${hub_xyz//./ } )
|
||||||
hub_xy="${split[0]}.${split[1]}"
|
hub_xy="${split[0]}.${split[1]}"
|
||||||
# add .dev on hub_xy so it's 1.0.dev
|
# add .dev on hub_xy so it's 1.0.dev
|
||||||
if [[ ! -z "${split[3]}" ]]; then
|
if [[ ! -z "${split[3]:-}" ]]; then
|
||||||
hub_xy="${hub_xy}.${split[3]}"
|
hub_xy="${hub_xy}.${split[3]}"
|
||||||
|
latest=0
|
||||||
|
else
|
||||||
|
latest=1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,3 +34,11 @@ docker tag $DOCKER_REPO:$DOCKER_TAG $DOCKER_REPO:$hub_xy
|
|||||||
docker push $DOCKER_REPO:$hub_xy
|
docker push $DOCKER_REPO:$hub_xy
|
||||||
docker tag $ONBUILD:$DOCKER_TAG $ONBUILD:$hub_xy
|
docker tag $ONBUILD:$DOCKER_TAG $ONBUILD:$hub_xy
|
||||||
docker push $ONBUILD:$hub_xyz
|
docker push $ONBUILD:$hub_xyz
|
||||||
|
|
||||||
|
# if building a stable release, tag latest as well
|
||||||
|
if [[ "$latest" == "1" ]]; then
|
||||||
|
docker tag $DOCKER_REPO:$DOCKER_TAG $DOCKER_REPO:latest
|
||||||
|
docker push $DOCKER_REPO:latest
|
||||||
|
docker tag $ONBUILD:$DOCKER_TAG $ONBUILD:latest
|
||||||
|
docker push $ONBUILD:latest
|
||||||
|
fi
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
version_info = (
|
version_info = (
|
||||||
0,
|
0,
|
||||||
9,
|
9,
|
||||||
4,
|
6,
|
||||||
"", # release (b1, rc1, or "" for final or dev)
|
"", # release (b1, rc1, or "" for final or dev)
|
||||||
# "dev", # dev or nothing
|
# "dev", # dev or nothing
|
||||||
)
|
)
|
||||||
|
@@ -427,6 +427,8 @@ class BaseHandler(RequestHandler):
|
|||||||
- else: /hub/home
|
- else: /hub/home
|
||||||
"""
|
"""
|
||||||
next_url = self.get_argument('next', default='')
|
next_url = self.get_argument('next', default='')
|
||||||
|
# protect against some browsers' buggy handling of backslash as slash
|
||||||
|
next_url = next_url.replace('\\', '%5C')
|
||||||
if (next_url + '/').startswith(
|
if (next_url + '/').startswith(
|
||||||
(
|
(
|
||||||
'%s://%s/' % (self.request.protocol, self.request.host),
|
'%s://%s/' % (self.request.protocol, self.request.host),
|
||||||
@@ -434,15 +436,23 @@ class BaseHandler(RequestHandler):
|
|||||||
)
|
)
|
||||||
):
|
):
|
||||||
# treat absolute URLs for our host as absolute paths:
|
# treat absolute URLs for our host as absolute paths:
|
||||||
|
# below, redirects that aren't strictly paths
|
||||||
parsed = urlparse(next_url)
|
parsed = urlparse(next_url)
|
||||||
next_url = parsed.path
|
next_url = parsed.path
|
||||||
if parsed.query:
|
if parsed.query:
|
||||||
next_url = next_url + '?' + parsed.query
|
next_url = next_url + '?' + parsed.query
|
||||||
if parsed.hash:
|
if parsed.fragment:
|
||||||
next_url = next_url + '#' + parsed.hash
|
next_url = next_url + '#' + parsed.fragment
|
||||||
if next_url and (urlparse(next_url).netloc or not next_url.startswith('/')):
|
|
||||||
|
# if it still has host info, it didn't match our above check for *this* host
|
||||||
|
if next_url and (
|
||||||
|
'://' in next_url
|
||||||
|
or next_url.startswith('//')
|
||||||
|
or not next_url.startswith('/')
|
||||||
|
):
|
||||||
self.log.warning("Disallowing redirect outside JupyterHub: %r", next_url)
|
self.log.warning("Disallowing redirect outside JupyterHub: %r", next_url)
|
||||||
next_url = ''
|
next_url = ''
|
||||||
|
|
||||||
if next_url and next_url.startswith(url_path_join(self.base_url, 'user/')):
|
if next_url and next_url.startswith(url_path_join(self.base_url, 'user/')):
|
||||||
# add /hub/ prefix, to ensure we redirect to the right user's server.
|
# add /hub/ prefix, to ensure we redirect to the right user's server.
|
||||||
# The next request will be handled by SpawnHandler,
|
# The next request will be handled by SpawnHandler,
|
||||||
|
@@ -409,10 +409,13 @@ def test_login_strip(app):
|
|||||||
(False, '/has?query#andhash', '/has?query#andhash'),
|
(False, '/has?query#andhash', '/has?query#andhash'),
|
||||||
|
|
||||||
# next_url outside is not allowed
|
# next_url outside is not allowed
|
||||||
|
(False, 'relative/path', ''),
|
||||||
(False, 'https://other.domain', ''),
|
(False, 'https://other.domain', ''),
|
||||||
(False, 'ftp://other.domain', ''),
|
(False, 'ftp://other.domain', ''),
|
||||||
(False, '//other.domain', ''),
|
(False, '//other.domain', ''),
|
||||||
]
|
(False, '///other.domain/triple', ''),
|
||||||
|
(False, '\\\\other.domain/backslashes', ''),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
@pytest.mark.gen_test
|
@pytest.mark.gen_test
|
||||||
def test_login_redirect(app, running, next_url, location):
|
def test_login_redirect(app, running, next_url, location):
|
||||||
@@ -426,7 +429,7 @@ def test_login_redirect(app, running, next_url, location):
|
|||||||
|
|
||||||
url = 'login'
|
url = 'login'
|
||||||
if next_url:
|
if next_url:
|
||||||
if '//' not in next_url:
|
if '//' not in next_url and next_url.startswith('/'):
|
||||||
next_url = ujoin(app.base_url, next_url, '')
|
next_url = ujoin(app.base_url, next_url, '')
|
||||||
url = url_concat(url, dict(next=next_url))
|
url = url_concat(url, dict(next=next_url))
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ function get_hub_version() {
|
|||||||
split=( ${hub_xyz//./ } )
|
split=( ${hub_xyz//./ } )
|
||||||
hub_xy="${split[0]}.${split[1]}"
|
hub_xy="${split[0]}.${split[1]}"
|
||||||
# add .dev on hub_xy so it's 1.0.dev
|
# add .dev on hub_xy so it's 1.0.dev
|
||||||
if [[ ! -z "${split[3]}" ]]; then
|
if [[ ! -z "${split[3]:-}" ]]; then
|
||||||
hub_xy="${hub_xy}.${split[3]}"
|
hub_xy="${hub_xy}.${split[3]}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user