@@ -14,11 +14,12 @@ FROM {{ prefix }}debian:bookworm
1414USER root
1515WORKDIR /root
1616
17- LABEL maintainer="Pavel Shirshov"
18-
1917COPY ["sources.list.{{ CONFIGURED_ARCH }}", "/etc/apt/sources.list"]
2018COPY ["no-check-valid-until", "/etc/apt/apt.conf.d"]
2119COPY ["apt-retries-count", "/etc/apt/apt.conf.d"]
20+ # Install certificates by disabling the peer verification
21+ RUN apt -o Acquire::https::Verify-Peer=false update && \
22+ apt -o Acquire::https::Verify-Peer=false install -y ca-certificates
2223
2324## Make apt-get non-interactive
2425ENV DEBIAN_FRONTEND=noninteractive
@@ -51,7 +52,7 @@ RUN apt-get update \
5152{% if PTF_ENV_PY_VER == "mixed" %}
5253 libboost-atomic1.71.0 \
5354{% else %}
54- libboost-atomic1.74 .0 \
55+ libboost-atomic1.81 .0 \
5556 flex \
5657 bison \
5758 tcpd \
@@ -102,19 +103,19 @@ RUN apt-get update \
102103 quilt \
103104 && rm -rf /var/lib/apt/lists/*
104105
105- # Install Go toolchain for building grpcurl and gnoic from source
106- # to ensure they use a patched Go stdlib (GO-2026-4337: crypto/tls )
106+ # Install Go toolchain for building grpcurl and gnmic from source
107+ # to ensure they use a patched Go stdlib (GO-2026-5039: net/textproto )
107108{% if CONFIGURED_ARCH == "armhf" %}
108109RUN GO_ARCH=armv6l \
109- && GO_SHA256=7d4f0d266d871301e08ef4ac31c56e66048688893b2848392e5c600276351ee8 \
110+ && GO_SHA256=492d69badee59cae12e9a36282dfce94041bd4aac88fdddea575a7d99a2bd05d \
110111{% elif CONFIGURED_ARCH == "arm64" %}
111112RUN GO_ARCH=arm64 \
112- && GO_SHA256=ec342e7389b7f489564ed5463c63b16cf8040023dabc7861256677165a8c0e2b \
113+ && GO_SHA256=c30bf9e156a54ea4e31fbbbf31a712b32734b58cc9a22426fa5ee632d0885124 \
113114{% else %}
114115RUN GO_ARCH=amd64 \
115- && GO_SHA256=00859d7bd6defe8bf84d9db9e57b9a4467b2887c18cd93ae7460e713db774bc1 \
116+ && GO_SHA256=34f14304e856893f4ba30c2cacfe93906e9de7915c5f6aaaf3a81cdccd7ba30b \
116117{% endif %}
117- && GO_VERSION=1.25.9 \
118+ && GO_VERSION=1.25.11 \
118119 && curl -L "https://go.dev/dl/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz" -o /tmp/go.tar.gz \
119120 && echo "${GO_SHA256} /tmp/go.tar.gz" | sha256sum -c - \
120121 && tar -C /usr/local -xzf /tmp/go.tar.gz \
@@ -158,7 +159,10 @@ RUN set -eux \
158159 && ldconfig \
159160 && ln -sf /usr/local/bin/influxdb3 /usr/local/bin/influxd \
160161 && rm -f "influxdb3-core-${INFLUXDB_VERSION}_${INFLUXDB_ARCH}.tar.gz" \
161- && rm -rf "/tmp/influxdb3-core-${INFLUXDB_VERSION}"
162+ && rm -rf "/tmp/influxdb3-core-${INFLUXDB_VERSION}" \
163+ && pip3 install --target /usr/local/lib/influxdb3-python/lib/python3.13/site-packages "pip>=26.1" \
164+ && NEWPIP=$(ls -d /usr/local/lib/influxdb3-python/lib/python3.13/site-packages/pip-*.dist-info | sort -V | tail -1) \
165+ && find /usr/local/lib/influxdb3-python/lib/python3.13/site-packages -maxdepth 1 -name 'pip-*.dist-info' ! -path "$NEWPIP" -exec rm -rf {} +
162166{% endif %}
163167
164168{% if PTF_ENV_PY_VER == "py3" %}
@@ -209,7 +213,7 @@ RUN rm -rf /debs \
209213{% endif %}
210214 && git clone https://github.com/sflow/sflowtool \
211215 && cd sflowtool \
212- && git checkout v6.04 \
216+ && git checkout v6.09 \
213217 && ./boot.sh \
214218 && ./configure \
215219 && make \
@@ -225,17 +229,17 @@ RUN rm -rf /debs \
225229 && make install \
226230 && cd .. \
227231 && rm -fr OpenBFDD \
228- && wget https://github.com/nanomsg/nanomsg/archive/1.0.0 .tar.gz \
229- && tar xvfz 1.0.0 .tar.gz \
230- && cd nanomsg-1.0.0 \
232+ && wget https://github.com/nanomsg/nanomsg/archive/1.2.2 .tar.gz \
233+ && tar xvfz 1.2.2 .tar.gz \
234+ && cd nanomsg-1.2.2 \
231235 && mkdir -p build \
232236 && cd build \
233237 && cmake .. \
234238 && make install \
235239 && ldconfig \
236240 && cd ../.. \
237- && rm -fr nanomsg-1.0.0 \
238- && rm -f 1.0.0 .tar.gz \
241+ && rm -fr nanomsg-1.2.2 \
242+ && rm -f 1.2.2 .tar.gz \
239243{% if PTF_ENV_PY_VER == "mixed" %}
240244 && pip install cffi \
241245 && pip install nnpy \
@@ -274,7 +278,7 @@ COPY ["tacacs+", "/etc/default"]
274278# Workaround: Tornado installed outside of the
275279# virtualenv as the call to the process API
276280# Ansible -> Supervisor -> ExaBGP -> Process API
277- # causes the process API to have a restricted
281+ # causes the process API to have a restricted
278282# environment without access to the virtualenv.
279283{% if PTF_ENV_PY_VER == "py3" %}
280284 RUN pip3 install --break-system-packages "tornado>=6.5.5"
@@ -283,6 +287,9 @@ COPY ["tacacs+", "/etc/default"]
283287
284288RUN python3 -m venv env-python3
285289# Activating a virtualenv. The virtualenv automatically works for RUN, ENV and CMD.
290+ # Python 3 reproducible build hooks are not used after this point in docker-ptf.
291+ # Once PATH is switched to the virtualenv, pip3 resolves to the venv binary
292+ # instead of the host pip3 wrapper, so run_pip_command is bypassed.
286293ENV VIRTUAL_ENV=/root/env-python3
287294ARG BACKUP_OF_PATH="$PATH"
288295ENV PATH="$VIRTUAL_ENV/bin:$PATH"
@@ -295,11 +302,11 @@ RUN pip3 install --upgrade pip
295302RUN python3 -m pip install --upgrade --ignore-installed pip
296303{% endif %}
297304
298- # For py3 image the following offending packages below do not use the updated
299- # setuptools on Python 3.9. The packages downgrade setuptools
305+ # For py3 image the following offending packages below do not use the updated
306+ # setuptools on Python 3.9. The packages downgrade setuptools
300307# to 40.x causing further installations to fail
301308{% if PTF_ENV_PY_VER == "py3" %}
302- {% set offending_packages = ["supervisor" , "ipython" , "exabgp==4.2.25" , "grpcio-tools" , "pybrctl" , "pyrasite" , "scapy==2.5.0 " , "thrift" ] %}
309+ {% set offending_packages = ["supervisor" , "ipython" , "exabgp==4.2.25" , "grpcio-tools" , "pybrctl" , "pyrasite" , "scapy" , "thrift" ] %}
303310{{ install_offending_packages(offending_packages) }}
304311{% else %}
305312RUN pip3 install setuptools \
@@ -309,17 +316,15 @@ RUN pip3 install setuptools \
309316 && pip3 install grpcio-tools \
310317 && pip3 install pybrctl \
311318 && pip3 install pyrasite \
312- && pip3 install scapy==2.5.0 \
319+ && pip3 install scapy \
313320 && pip3 install thrift
314321{% endif %}
315322
316- # Install all python modules from pypi. python3-scapy is exception,
323+ # Install all python modules from pypi. python3-scapy is exception,
317324# ptf debian package requires python3-scapy
325+ RUN pip3 install Flask \
318326{% if PTF_ENV_PY_VER == "py3" %}
319- RUN pip3 install Flask \
320327 && pip3 install Werkzeug \
321- {% else %}
322- RUN pip3 install Flask \
323328{% endif %}
324329 && pip3 install Cython \
325330 && pip3 install cffi \
@@ -329,15 +334,12 @@ RUN pip3 install Flask \
329334 && pip3 install pysubnettree \
330335 && pip3 install paramiko \
331336 && pip3 install "tornado>=6.5.5" \
332- && pip3 install Flask \
333- && pip3 install exabgp \
334337 && pip3 install pyaml \
335338 && pip3 install pyro4 rpyc \
336339 && pip3 install unittest-xml-reporting \
337340 && pip3 install python-libpcap \
338- && pip3 install enum34 \
339341 && pip3 install grpcio \
340- && pip3 install six==1.16.0 \
342+ && pip3 install six \
341343 && pip3 install itsdangerous \
342344 && pip3 install retrying \
343345 && pip3 install jinja2
@@ -361,7 +363,8 @@ RUN set -e; \
361363{% endif %}
362364
363365# Ensure setuptools >= 70.0.0 to address GHSA-cx63-2mw6-8hw5
364- RUN pip3 install "setuptools>=70.0.0"
366+ # Upgrade lxml to address GHSA-vfmq-68hx-4jfw
367+ RUN pip3 install "setuptools>=70.0.0" "lxml>=5.3.2"
365368
366369## Adjust sshd settings
367370RUN mkdir /var/run/sshd \
@@ -412,50 +415,38 @@ RUN cd gnxi \
412415# Deactivating a virtualenv.
413416# ENV PATH="$BACKUP_OF_PATH"
414417
415- # Build gnoic from source with patched Go and golang.org/x/* deps
416- # upgraded to latest to address current and future golang.org/x/* CVEs.
417- RUN git clone https://github.com/karimra/gnoic.git \
418- && cd gnoic \
419- && git checkout 27bc5a6 \
420- && go get google.golang.org/grpc@v1.79.3 \
421- && go get github.com/go-viper/mapstructure/v2@v2.4.0 \
422- && go get github.com/go-jose/go-jose/v4@latest \
423- && go get golang.org/x/crypto@latest golang.org/x/net@latest golang.org/x/text@latest golang.org/x/sys@latest golang.org/x/oauth2@latest \
424- && go mod tidy \
425- && go build -o /usr/local/bin/gnoic . \
426- && cd .. \
427- && rm -rf gnoic /root/go/pkg/mod /root/.cache/go-build
428-
429- # Build gnmic from source with upgraded deps to address known CVEs
430- COPY gocloud-patches/ /tmp/gocloud-patches/
431- RUN GNMIC_VERSION=v0.43.0 \
432- && git clone --depth 1 --branch "${GNMIC_VERSION}" https://github.com/openconfig/gnmic.git /tmp/gnmic \
418+ # Build gnmic from source at a pinned upstream main commit. Picks up the
419+ # dependency fixes merged after v0.45.0 (grpc 1.79.3, otel-sdk 1.43.0,
420+ # go-git 5.19.0, prometheus 0.311.3, etc.) that address the CVEs which
421+ # forced removal in #27059. The golang.org/x/* modules are additionally
422+ # upgraded to latest to clear current/future golang.org/x/* CVEs (the
423+ # pinned commit still locks older x/crypto, x/net, etc.). Temporary until
424+ # the next tagged gnmic release ships.
425+ RUN GNMIC_REV=653dc5dd4ddcd3bd4197317875a10c1ce8b06653 \
426+ && git clone https://github.com/openconfig/gnmic.git /tmp/gnmic \
433427 && cd /tmp/gnmic \
434- && go get google.golang.org/grpc@v1.79.3 \
435- && go get github.com/cloudflare/circl@v1.6.3 \
436- && go get github.com/go-git/go-git/v5@latest \
437- && go get github.com/nats-io/nats-server/v2@latest \
438- && go get go.opentelemetry.io/otel/sdk@latest \
439- && go get github.com/docker/docker@latest \
440- && go get github.com/go-jose/go-jose/v4@latest \
441- && go get github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream@latest github.com/aws/aws-sdk-go-v2/service/s3@latest github.com/aws/aws-sdk-go-v2/feature/s3/manager@latest \
428+ && git checkout "${GNMIC_REV}" \
442429 && go get golang.org/x/crypto@latest golang.org/x/net@latest golang.org/x/text@latest golang.org/x/sys@latest golang.org/x/oauth2@latest \
443- && go get gocloud.dev@v0.25.1-0.20220408200107-09b10f7359f7 \
444430 && go mod tidy \
445- && GOCLOUD_DIR="$(go list -m -f '{{ '{{' }}.Dir{{ '}}' }}' gocloud.dev)" \
446- && chmod -R +w "$GOCLOUD_DIR" \
447- && patch --forward -d "$GOCLOUD_DIR" -p1 < /tmp/gocloud-patches/0001-fix-aws-sdk-go-v2-pointer-api-changes.patch \
448431 && go build -o /usr/local/bin/gnmic . \
449432 && chmod +x /usr/local/bin/gnmic \
450- && rm -rf /tmp/gnmic /tmp/gocloud-patches / root/go/pkg/mod /root/.cache/go-build
433+ && rm -rf /tmp/gnmic /root/go/pkg/mod /root/.cache/go-build
451434
452435# Remove Go toolchain to reduce image size
453436RUN rm -rf /usr/local/go "$(go env GOPATH 2>/dev/null || echo $HOME/go)"
454437ENV PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
455438
456439{% if PTF_ENV_PY_VER == "py3" %}
457- # Install the python-saithrift into the virtual environment
458- RUN echo "/usr/lib/python3/dist-packages/saithrift-0.9-py3.11.egg" >> /root/env-python3/lib/python3.11/site-packages/easy-install.pth
440+ # Register the python-saithrift egg on the virtualenv path. Use an
441+ # executable .pth line that globs for the egg at every interpreter
442+ # startup, so the path is resolved dynamically rather than pinned to a
443+ # specific Python minor version. This keeps switch_sai_thrift importable
444+ # even after test_update_saithrift_ptf swaps in a saithrift deb built for
445+ # a different Python minor (e.g. py3.13 from a Trixie/OS13 DUT image).
446+ # saithrift is thrift-generated pure Python, so the egg loads across py3.x.
447+ RUN PYVER=$(python3 -c 'import sys; print("%d.%d" % sys.version_info[:2])') \
448+ && echo "import glob, sys; sys.path.extend(glob.glob('"'"'/usr/lib/python3/dist-packages/saithrift-0.9-py3.*.egg'"'"'))" \
449+ >> "/root/env-python3/lib/python${PYVER}/site-packages/easy-install.pth"
459450{% endif %}
460451
461452# {% if PTF_ENV_PY_VER == "py3" %}
@@ -490,6 +481,17 @@ RUN echo "/root/env-python3/lib/python3.11/site-packages" > /usr/lib/python3/dis
490481
491482RUN echo "PYTHONPATH=/root/env-python3/lib/python3.11/site-packages" >> /etc/environment
492483
484+ # Final system-level security upgrade: ensure every Debian package is at its
485+ # latest patched version. This must run AFTER all apt-get install / dpkg -i
486+ # steps so nothing slips through.
487+ # The build system pins package versions via /etc/apt/preferences.d/01-versions-deb.
488+ # Remove the pin so apt-get upgrade can pull in the latest security patches.
489+ RUN rm -f /etc/apt/preferences.d/01-versions-deb \
490+ && apt-get update \
491+ && apt-get upgrade -y \
492+ && apt-get dist-upgrade -y \
493+ && rm -rf /var/lib/apt/lists/*
494+
493495COPY ["*.ini", "/etc/ptf/"]
494496EXPOSE 22 8009
495497
0 commit comments