mirror of
https://github.com/pyenv/pyenv.git
synced 2024-11-14 20:39:55 -05:00
Re-allow paths in .python-version provided that they resolve to within the versions dir (#2442)
* Fixes #2430 while still preventing CVE-2022-35861 * Adds a skipped version message to stderr Co-authored-by: Ivan Pozdeev <vano@mail.mipt.ru>
This commit is contained in:
parent
fdabd14c2b
commit
47b0ce77c0
2 changed files with 48 additions and 11 deletions
|
@ -5,18 +5,33 @@ set -e
|
||||||
|
|
||||||
VERSION_FILE="$1"
|
VERSION_FILE="$1"
|
||||||
|
|
||||||
|
function is_version_safe() {
|
||||||
|
# As needed, check that the constructed path exists as a child path of PYENV_ROOT/versions
|
||||||
|
version="$1"
|
||||||
|
if [[ "$version" == ".." || "$version" == */* ]]; then
|
||||||
|
# Sanity check the value of version to prevent malicious path-traversal
|
||||||
|
(
|
||||||
|
cd "$PYENV_ROOT/versions/$version" &>/dev/null || exit 1
|
||||||
|
[[ "$PWD" == "$PYENV_ROOT/versions/"* ]]
|
||||||
|
)
|
||||||
|
return $?
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
if [ -s "$VERSION_FILE" ]; then
|
if [ -s "$VERSION_FILE" ]; then
|
||||||
# Read the first non-whitespace word from the specified version file.
|
# Read the first non-whitespace word from the specified version file.
|
||||||
# Be careful not to load it whole in case there's something crazy in it.
|
# Be careful not to load it whole in case there's something crazy in it.
|
||||||
IFS="${IFS}"$'\r'
|
IFS="$IFS"$'\r'
|
||||||
sep=
|
sep=
|
||||||
while read -n 1024 -r version _ || [[ $version ]]; do
|
while read -n 1024 -r version _ || [[ $version ]]; do
|
||||||
if [[ -z $version || $version == \#* ]]; then
|
if [[ -z "$version" || "$version" == \#* ]]; then
|
||||||
# Skip empty lines and comments
|
# Skip empty lines and comments
|
||||||
continue
|
continue
|
||||||
elif [ "$version" = ".." ] || [[ $version == */* ]]; then
|
elif ! is_version_safe "$version"; then
|
||||||
# The version string is used to construct a path and we skip dubious values.
|
# CVE-2022-35861 allowed arbitrary code execution in some contexts and is mitigated by is_version_safe.
|
||||||
# This prevents issues such as path traversal (CVE-2022-35861).
|
echo "pyenv: invalid version \`$version' ignored in \`$VERSION_FILE'" >&2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
printf "%s%s" "$sep" "$version"
|
printf "%s%s" "$sep" "$version"
|
||||||
|
|
|
@ -83,14 +83,36 @@ IN
|
||||||
assert_success "3.9.3:3.8.9:2.7.16"
|
assert_success "3.9.3:3.8.9:2.7.16"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "skips relative path traversal" {
|
@test "skips \`..' relative path traversal" {
|
||||||
|
echo '..' > my-version
|
||||||
|
run pyenv-version-file-read my-version
|
||||||
|
assert_failure "pyenv: invalid version \`..' ignored in \`my-version'"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "skips glob path traversal" {
|
||||||
cat > my-version <<IN
|
cat > my-version <<IN
|
||||||
|
../*
|
||||||
3.9.3
|
3.9.3
|
||||||
3.8.9
|
|
||||||
..
|
|
||||||
./*
|
|
||||||
2.7.16
|
|
||||||
IN
|
IN
|
||||||
run pyenv-version-file-read my-version
|
run pyenv-version-file-read my-version
|
||||||
assert_success "3.9.3:3.8.9:2.7.16"
|
assert_success <<OUT
|
||||||
|
pyenv: invalid version \`../\*' ignored in \`my-version'
|
||||||
|
3.9.3
|
||||||
|
OUT
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "allows relative paths that exist and stay within versions" {
|
||||||
|
venv=3.10.3/envs/../test
|
||||||
|
mkdir -p "${PYENV_ROOT}/versions/${venv}"
|
||||||
|
echo -n "${venv}" > my-version
|
||||||
|
run pyenv-version-file-read my-version
|
||||||
|
assert_success "${venv}"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "skips relative paths that lead outside of versions" {
|
||||||
|
venv=../3.10.3/envs/test
|
||||||
|
mkdir -p "${PYENV_ROOT}/versions/${venv}"
|
||||||
|
echo -n "${venv}" > my-version
|
||||||
|
run pyenv-version-file-read my-version
|
||||||
|
assert_failure
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue