Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 01aad64

Browse files
[python]-setuptools-GHSA-r9hx-vwmv-q579-remove setuptools-65.5.0-py3-none-any.whl (#866)
* [python]-setuptools-GHSA-r9hx-vwmv-q579-remove setuptools-65.5.0-py3-none-any.whl * changes based on comments on pr #866 * Tried to answer acc. to last comment * Added tests to validate when skipVulnerabilityPatching=true
1 parent 7d807c2 commit 01aad64

6 files changed

Lines changed: 247 additions & 31 deletions

src/python/devcontainer-feature.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "python",
3-
"version": "1.4.0",
3+
"version": "1.4.1",
44
"name": "Python",
55
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/python",
66
"description": "Installs the provided version of Python, as well as PIPX, and other common Python utilities. JupyterLab is conditionally installed with the python feature. Note: May require source code compilation.",

src/python/install.sh

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
PYTHON_VERSION="${VERSION:-"latest"}" # 'system' or 'os-provided' checks the base image first, else installs 'latest'
1111
INSTALL_PYTHON_TOOLS="${INSTALLTOOLS:-"true"}"
12+
SKIP_VULNERABILITY_PATCHING="${SKIPVULNERABILITYPATCHING:-"false"}"
1213
OPTIMIZE_BUILD_FROM_SOURCE="${OPTIMIZE:-"false"}"
1314
ENABLE_SHARED_FROM_SOURCE="${ENABLESHARED:-"false"}"
1415
PYTHON_INSTALL_PATH="${INSTALLPATH:-"/usr/local/python"}"
@@ -750,12 +751,40 @@ if [[ "${INSTALL_PYTHON_TOOLS}" = "true" ]] && [[ -n "${PYTHON_SRC}" ]]; then
750751
done
751752

752753
# Temporary: Removes “setup tools” metadata directory due to https://github.com/advisories/GHSA-r9hx-vwmv-q579
753-
754-
VULNERABLE_VERSIONS=("3.10" "3.11")
755-
RUN_TIME_PY_VER_DETECT=$(${PYTHON_SRC} --version 2>&1)
756-
PY_MAJOR_MINOR_VER=${RUN_TIME_PY_VER_DETECT:7:4};
757-
if [[ ${VULNERABLE_VERSIONS[*]} =~ $PY_MAJOR_MINOR_VER ]]; then
758-
rm -rf ${PIPX_HOME}/shared/lib/"python${PY_MAJOR_MINOR_VER}"/site-packages/setuptools-65.5.0.dist-info
754+
if [[ $SKIP_VULNERABILITY_PATCHING = "false" ]]; then
755+
VULNERABLE_VERSIONS=("3.10" "3.11")
756+
RUN_TIME_PY_VER_DETECT=$(${PYTHON_SRC} --version 2>&1)
757+
PY_MAJOR_MINOR_VER=${RUN_TIME_PY_VER_DETECT:7:4};
758+
if [[ ${VULNERABLE_VERSIONS[*]} =~ $PY_MAJOR_MINOR_VER ]]; then
759+
rm -rf ${PIPX_HOME}/shared/lib/"python${PY_MAJOR_MINOR_VER}"/site-packages/setuptools-65.5.0.dist-info
760+
if [[ -e "/usr/local/lib/python${PY_MAJOR_MINOR_VER}/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl" ]]; then
761+
# remove the vulnerable setuptools-65.5.0-py3-none-any.whl file
762+
rm /usr/local/lib/python${PY_MAJOR_MINOR_VER}/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl
763+
# create and change to the setuptools_downloaded directory
764+
mkdir -p /tmp/setuptools_downloaded
765+
cd /tmp/setuptools_downloaded
766+
# download the source distribution for setuptools using pip
767+
pip download setuptools==65.5.1 --no-binary :all:
768+
# extract the filename of the setuptools-*.tar.gz file
769+
filename=$(find . -maxdepth 1 -type f)
770+
# create a directory to store unpacked contents of the source distribution
771+
mkdir -p /tmp/setuptools_src_dist
772+
# extract the contents inside the new directory
773+
tar -xzf $filename -C /tmp/setuptools_src_dist
774+
# move to the setuptools-* directory inside /setuptools_src_dist
775+
cd /tmp/setuptools_src_dist/setuptools-65.5.1/
776+
# look for setup.py file in the current directory and create a wheel file
777+
python setup.py bdist_wheel
778+
# move inside the dist directory in pwd
779+
cd dist
780+
# copy this file to the ensurepip/_bundled directory
781+
cp setuptools-65.5.1-py3-none-any.whl /usr/local/lib/python${PY_MAJOR_MINOR_VER}/ensurepip/_bundled/
782+
# replace the version in __init__.py file with the installed version
783+
sed -i 's/_SETUPTOOLS_VERSION = \"65\.5\.0\"/_SETUPTOOLS_VERSION = "65.5.1"/g' /usr/local/lib/"python${PY_MAJOR_MINOR_VER}"/ensurepip/__init__.py
784+
# cleanup created dir's
785+
rm -rf /tmp/setuptools_downloaded /tmp/setuptools_src_dist
786+
fi
787+
fi
759788
fi
760789

761790
rm -rf /tmp/pip-tmp

test/python/install_python310_setuptools_vulnerability.sh

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,51 @@ check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bi
6464
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
6565
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
6666
67-
checkVulnerableDir()
67+
checkVulnerableFile_OR_DIR()
6868
{
69-
DIRECTORY=$1
70-
VERSION=$2
71-
72-
if [[ -d $DIRECTORY ]] ; then
73-
echoStderr "❌ check for vulnerable setuptools version failed for python ${VERSION}."
74-
return 1
69+
for arg in "$@"; do
70+
if [[ -e $arg ]]; then
71+
echo -e "\n✅ Vulnerable:- ${arg} - exists in v3.10 as Vulnerability Patching has been skipped."
72+
else
73+
echo -e "\n❌ Vulnerable:- ${arg} - don't exist in v3.10 as Vulnerability Patching has not been skipped."
74+
fi
75+
done
76+
}
77+
78+
# print setuptools
79+
check "Show All Files/Folders which include setuptools" bash -c 'find / -name "*setuptools*"'
80+
81+
# only for 3.10
82+
checkVulnerableFile_OR_DIR "/usr/local/py-utils/shared/lib/python3.10/site-packages/setuptools-65.5.0.dist-info" "/usr/local/lib/python3.10/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl"
83+
84+
# Function to check if a package is installed
85+
checkPackageInstalled() {
86+
if python -c "import $1" &>/dev/null; then
87+
echo -e "\n✅ Passed! \n$1 is installed"
7588
else
76-
echo "✅ Passed! Either the container does not have vulnerable version or vulnerable version specific directory got removed."
77-
return 0
89+
echo -e "$1 is NOT installed\n"
90+
echoStderr "❌ check failed."
7891
fi
7992
}
8093
81-
# only for 3.10
82-
checkVulnerableDir "/usr/local/py-utils/shared/lib/python3.10/site-packages/setuptools-65.5.0.dist-info" "3.10"
94+
# Function to install a package using pip
95+
installPackage() {
96+
python3 -m pip install "$1"
97+
}
98+
99+
checkPipWorkingCorrectly() {
100+
echo -e "\n🧪 Testing whether pip install works fine \n"
101+
# List of packages to install via pip
102+
packages=("numpy" "requests" "matplotlib")
103+
# Install packages and check if installation was successful
104+
for package in "${packages[@]}"; do
105+
echo -e "\n🧪 Testing pip install $package\n"
106+
installPackage "$package"
107+
checkPackageInstalled "$package"
108+
done
109+
}
110+
111+
checkPipWorkingCorrectly
83112
84113
# Report result
85114
reportResults
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Optional: Import test library
5+
source dev-container-features-test-lib
6+
7+
FAILED=()
8+
9+
echoStderr()
10+
{
11+
echo "$@" 1>&2
12+
}
13+
14+
check-version-ge() {
15+
LABEL=$1
16+
CURRENT_VERSION=$2
17+
REQUIRED_VERSION=$3
18+
shift
19+
echo -e "\n🧪 Testing $LABEL: '$CURRENT_VERSION' is >= '$REQUIRED_VERSION'"
20+
local GREATER_VERSION=$((echo ${CURRENT_VERSION}; echo ${REQUIRED_VERSION}) | sort -V | tail -1)
21+
if [ "${CURRENT_VERSION}" == "${GREATER_VERSION}" ]; then
22+
echo "✅ Passed!"
23+
return 0
24+
else
25+
echoStderr "❌ $LABEL check failed."
26+
FAILED+=("$LABEL")
27+
return 1
28+
fi
29+
}
30+
31+
checkPythonPackageVersion()
32+
{
33+
PACKAGE=$1
34+
REQUIRED_VERSION=$2
35+
36+
current_version=$(python -c "import importlib.metadata; print(importlib.metadata.version('${PACKAGE}'))")
37+
check-version-ge "${PACKAGE}-requirement" "${current_version}" "${REQUIRED_VERSION}"
38+
}
39+
40+
checkPythonPackageVersion "setuptools" "65.5.1"
41+
42+
# Check that tools can execute - make sure something didn't get messed up in this scenario
43+
check "autopep8" autopep8 --version
44+
check "black" black --version
45+
check "yapf" yapf --version
46+
check "bandit" bandit --version
47+
check "flake8" flake8 --version
48+
check "mypy" mypy --version
49+
check "pycodestyle" pycodestyle --version
50+
check "pydocstyle" pydocstyle --version
51+
check "pylint" pylint --version
52+
check "pytest" pytest --version
53+
check "setuptools" pip list | grep setuptools
54+
55+
# Check paths in settings
56+
check "which autopep8" bash -c "which autopep8 | grep /usr/local/py-utils/bin/autopep8"
57+
check "which black" bash -c "which black | grep /usr/local/py-utils/bin/black"
58+
check "which yapf" bash -c "which yapf | grep /usr/local/py-utils/bin/yapf"
59+
check "which bandit" bash -c "which bandit | grep /usr/local/py-utils/bin/bandit"
60+
check "which flake8" bash -c "which flake8 | grep /usr/local/py-utils/bin/flake8"
61+
check "which mypy" bash -c "which mypy | grep /usr/local/py-utils/bin/mypy"
62+
check "which pycodestyle" bash -c "which pycodestyle | grep /usr/local/py-utils/bin/pycodestyle"
63+
check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bin/pydocstyle"
64+
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
65+
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
66+
67+
HL="\033[1;33m"
68+
N="\033[0;37m"
69+
70+
checkVulnerableFile_OR_DIR()
71+
{
72+
for arg in "$@"; do
73+
if [[ -e $arg ]]; then
74+
echo -e "\n${HL} Vulnerable:- ${N}${arg} - ${HL}EXISTS ${N}in v3.10 as skipVulnerabilityPatching=true"
75+
else
76+
echo -e "\n${HL} Vulnerable:- ${arg} - ${N}don't ${HL}EXISTS ${N}in v3.10 as skipVulnerabilityPatching=false"
77+
fi
78+
done
79+
}
80+
81+
# print setuptools
82+
check "Show All Files/Folders which include setuptools" bash -c 'find / -name "*setuptools*"'
83+
84+
# only for 3.10
85+
checkVulnerableFile_OR_DIR "/usr/local/py-utils/shared/lib/python3.10/site-packages/setuptools-65.5.0.dist-info" "/usr/local/lib/python3.10/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl"
86+
87+
# Function to check if a package is installed
88+
checkPackageInstalled() {
89+
if python -c "import $1" &>/dev/null; then
90+
echo -e "\n✅ Passed! \n$1 is installed"
91+
else
92+
echo -e "$1 is NOT installed\n"
93+
echoStderr "❌ check failed."
94+
fi
95+
}
96+
97+
# Function to install a package using pip
98+
installPackage() {
99+
python3 -m pip install "$1"
100+
}
101+
102+
checkPipWorkingCorrectly() {
103+
echo -e "\n🧪 Testing whether pip install works fine \n"
104+
# List of packages to install via pip
105+
packages=("numpy" "requests" "matplotlib")
106+
# Install packages and check if installation was successful
107+
for package in "${packages[@]}"; do
108+
echo -e "\n🧪 Testing pip install $package\n"
109+
installPackage "$package"
110+
checkPackageInstalled "$package"
111+
done
112+
}
113+
114+
checkPipWorkingCorrectly
115+
116+
# Report result
117+
reportResults

test/python/install_python311_setuptools_vulnerability.sh

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,22 +65,51 @@ check "which pydocstyle" bash -c "which pydocstyle | grep /usr/local/py-utils/bi
6565
check "which pylint" bash -c "which pylint | grep /usr/local/py-utils/bin/pylint"
6666
check "which pytest" bash -c "which pytest | grep /usr/local/py-utils/bin/pytest"
6767
68-
checkVulnerableDir()
68+
checkVulnerableFile_OR_DIR()
6969
{
70-
DIRECTORY=$1
71-
VERSION=$2
72-
73-
if [[ -d $DIRECTORY ]] ; then
74-
echoStderr "❌ check for vulnerable setuptools version failed for python ${VERSION}."
75-
return 1
70+
for arg in "$@"; do
71+
if [[ -e $arg ]]; then
72+
echo -e "\n✅ Vulnerable:- ${arg} - exists in v3.11 as Vulnerability Patching has been skipped."
73+
else
74+
echo -e "\n❌ Vulnerable:- ${arg} - don't exist in v3.11 as Vulnerability Patching has not been skipped."
75+
fi
76+
done
77+
}
78+
79+
# print setuptools
80+
check "Show All Files/Folders which include setuptools" bash -c 'find / -name "*setuptools*"'
81+
82+
# only for 3.11
83+
checkVulnerableFile_OR_DIR "/usr/local/py-utils/shared/lib/python3.11/site-packages/setuptools-65.5.0.dist-info" "/usr/local/lib/python3.11/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl"
84+
85+
# Function to check if a package is installed
86+
checkPackageInstalled() {
87+
if python -c "import $1" &>/dev/null; then
88+
echo -e "\n✅ Passed! \n$1 is installed"
7689
else
77-
echo "✅ Passed! Either the container does not have vulnerable version or vulnerable version specific directory got removed."
78-
return 0
90+
echo -e "$1 is NOT installed\n"
91+
echoStderr "❌ check failed."
7992
fi
8093
}
8194
82-
# only for 3.11
83-
checkVulnerableDir "/usr/local/py-utils/shared/lib/python3.11/site-packages/setuptools-65.5.0.dist-info" "3.11"
95+
# Function to install a package using pip
96+
installPackage() {
97+
python3 -m pip install "$1"
98+
}
99+
100+
checkPipWorkingCorrectly() {
101+
echo -e "\n🧪 Testing whether pip install works fine \n"
102+
# List of packages to install via pip
103+
packages=("numpy" "requests" "matplotlib")
104+
# Install packages and check if installation was successful
105+
for package in "${packages[@]}"; do
106+
echo -e "\n🧪 Testing pip install $package\n"
107+
installPackage "$package"
108+
checkPackageInstalled "$package"
109+
done
110+
}
111+
112+
checkPipWorkingCorrectly
84113
85114
# Report result
86115
reportResults

test/python/scenarios.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
{
2+
"install_python310_skipVulnerabilityPatching_true": {
3+
"image": "python:3.10",
4+
"features": {
5+
"python": {
6+
"version": "none",
7+
"installTools": true,
8+
"skipVulnerabilityPatching": true
9+
}
10+
}
11+
},
212
"install_python310_setuptools_vulnerability": {
313
"image": "python:3.10",
414
"features": {
515
"python": {
616
"version": "none",
7-
"installTools": true
17+
"installTools": true,
18+
"skipVulnerabilityPatching": false
819
}
920
}
1021
},
@@ -13,7 +24,8 @@
1324
"features": {
1425
"python": {
1526
"version": "none",
16-
"installTools": true
27+
"installTools": true,
28+
"skipVulnerabilityPatching": false
1729
}
1830
}
1931
},

0 commit comments

Comments
 (0)