Skip to content

Commit 2343e44

Browse files
committed
fix: remediate auditor and safe-synth task container CVEs
Signed-off-by: Matt Kornfield <[email protected]>
1 parent ba80434 commit 2343e44

11 files changed

Lines changed: 79 additions & 61 deletions

File tree

docker-bake.hcl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -932,9 +932,6 @@ target "auditor-tasks-docker" {
932932
contexts = {
933933
root-lib-source-artifacts = "target:root-lib-source-artifacts"
934934
root-busybox = "target:root-busybox"
935-
nmp-python-base = "target:nmp-python-base"
936-
nmp-python-dev-base = "target:nmp-python-dev-base"
937-
root-distroless-base-3-11 = "target:root-distroless-base-3-11"
938935
}
939936
dockerfile = "docker/Dockerfile.auditor-tasks"
940937
cache-to = maybe_registry_cache_to("auditor-tasks")

docker/Dockerfile.auditor-tasks

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11
# hadolint global ignore=DL3059
2-
# distroless images don't have a real shell - & and | are not enabled
2+
# The final image copies BusyBox shell utilities for parity with the task runtime.
33

4-
ARG NMP_PYTHON_BASE=nmp-python-base
4+
ARG AUDITOR_PYTHON_IMAGE=python:3.13.14-slim-trixie
55

66
ARG CACHE_HOME=/tmp/.cache
77

8-
FROM nmp-python-dev-base AS py-builder
9-
10-
ARG TARGETARCH
8+
FROM ${AUDITOR_PYTHON_IMAGE} AS py-builder
119

1210
ARG CACHE_HOME
11+
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \
12+
build-essential \
13+
ca-certificates \
14+
curl \
15+
g++ \
16+
gcc \
17+
git \
18+
libffi-dev \
19+
libpq-dev \
20+
libssl-dev \
21+
&& apt-get clean \
22+
&& rm -rf /var/lib/apt/lists/*
23+
24+
COPY --from=ghcr.io/astral-sh/uv:0.9.14 /uv /bin/uv
25+
26+
ENV UV_COMPILE_BYTECODE=1 \
27+
UV_LINK_MODE=copy
28+
29+
WORKDIR /app
1330
RUN mkdir -p ${CACHE_HOME} && chmod 777 ${CACHE_HOME}
1431

1532
# Create the directory structure to match the relative paths in pyproject.toml
@@ -57,7 +74,8 @@ RUN --mount=type=cache,target=/root/.cache/uv \
5774
"protobuf>=6.33.5,<7.0.0" \
5875
"langchain-core>=1.2.22" \
5976
"orjson>=3.11.6" \
60-
"nltk>=3.9.3"
77+
"cryptography>=48.0.1,<49" \
78+
"nltk>=3.10.0"
6179

6280
# CVE Remediation
6381
RUN --mount=type=cache,target=/root/.cache/uv \
@@ -68,13 +86,17 @@ RUN --mount=type=cache,target=/root/.cache/uv \
6886
"pyasn1>=0.6.3" \
6987
"wheel>=0.46.2" \
7088
"orjson>=3.11.6" \
71-
"nltk>=3.9.3"
89+
"cryptography>=48.0.1,<49" \
90+
"nltk>=3.10.0"
7291

73-
FROM ${NMP_PYTHON_BASE} AS base
92+
FROM ${AUDITOR_PYTHON_IMAGE} AS base
7493
ARG USERNAME=nvs
7594
ARG USER_UID=1000
7695
ARG USER_GID=1000
7796
WORKDIR /app
97+
RUN apt-get update && apt-get upgrade -y && \
98+
apt-get clean && \
99+
rm -rf /var/lib/apt/lists/*
78100
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
79101
useradd --uid ${USER_UID} --gid ${USER_GID} --create-home --shell /bin/bash ${USERNAME}
80102

docker/Dockerfile.nmp-unsloth-training

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
#
66
# Install steps:
77
# 1. `uv pip install unsloth --torch-backend=auto` plus explicit
8-
# `transformers==4.57.6` and `huggingface-hub==0.36.2` pins (transformers
9-
# 4.57.x requires hub <1.0; platform glue would otherwise pull hub 1.x).
8+
# `transformers==5.3.0` and `huggingface-hub==1.3.0` pins. Unsloth's
9+
# resolver allows transformers 5.3.0, and the explicit pins keep later
10+
# platform glue installs from re-solving the HF stack.
1011
# Unsloth's resolver still pulls unsloth_zoo
1112
# and the rest of the HF stack (trl, peft, accelerate, datasets,
1213
# bitsandbytes, xformers, etc.). `--overrides preserve_base_torch.txt`
@@ -70,8 +71,8 @@ ARG USERNAME=ubuntu
7071
ARG USER_UID=1000
7172
ARG USER_GID=1000
7273
ARG UNSLOTH_VERSION=2026.6.1
73-
ARG TRANSFORMERS_VERSION=4.57.6
74-
ARG HF_HUB_VERSION=0.36.2
74+
ARG TRANSFORMERS_VERSION=5.3.0
75+
ARG HF_HUB_VERSION=1.3.0
7576
ARG BITSANDBYTES_VERSION=0.49.2
7677
ARG BNB_MAX_JOBS=10
7778

docker/Dockerfile.safe-synthesizer-tasks

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
ARG PYTHON_VERSION=3.13
1212
ARG PYTHON_IMAGE=python:${PYTHON_VERSION}-slim-trixie
1313
ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.9.30
14-
ARG SAFE_SYNTHESIZER_RUNTIME_PACKAGE="nemo-safe-synthesizer[engine,cu129]==0.1.2"
14+
ARG SAFE_SYNTHESIZER_RUNTIME_PACKAGE="nemo-safe-synthesizer[engine,cu129]==0.1.7"
1515
ARG FLASHINFER_CU129_INDEX_URL="https://flashinfer.ai/whl/cu129"
1616
ARG PYTORCH_CU129_INDEX_URL="https://download.pytorch.org/whl/cu129"
17-
ARG VLLM_CU129_WHEEL="vllm @ https://github.com/vllm-project/vllm/releases/download/v0.20.0/vllm-0.20.0%2Bcu129-cp38-abi3-manylinux_2_31_x86_64.whl"
17+
ARG VLLM_CU129_INDEX_URL="https://wheels.vllm.ai/ee0da84ab9e04ac7610e28580af62c365e898389/cu129"
1818

1919
# =============================================================================
2020
# uv binary
@@ -29,7 +29,7 @@ ARG PYTHON_IMAGE
2929
ARG SAFE_SYNTHESIZER_RUNTIME_PACKAGE
3030
ARG FLASHINFER_CU129_INDEX_URL
3131
ARG PYTORCH_CU129_INDEX_URL
32-
ARG VLLM_CU129_WHEEL
32+
ARG VLLM_CU129_INDEX_URL
3333
ARG CONTAINER_VARIANT=cu129
3434
ARG USERNAME=nemo
3535
ARG USER_UID=1000
@@ -110,11 +110,10 @@ RUN printf '%s\n' \
110110
printf '%s\n' \
111111
"${SAFE_SYNTHESIZER_RUNTIME_PACKAGE}" \
112112
> /tmp/safe-synthesizer-runtime.txt && \
113-
printf '%s\n' \
114-
"${VLLM_CU129_WHEEL}" \
115-
> /tmp/vllm-cu129.txt && \
116113
printf '%s\n' \
117114
wandb==0.27.2 \
115+
'cryptography>=48.0.1,<49' \
116+
'pyarrow>=23.0.1,<24' \
118117
> /tmp/safe-synthesizer-overrides.txt
119118

120119
RUN --mount=type=cache,target=/root/.cache/uv \
@@ -157,12 +156,12 @@ RUN --mount=type=cache,target=/root/.cache/uv \
157156
UV_CACHE_DIR=/root/.cache/uv uv pip install --python /opt/venv/bin/python \
158157
--extra-index-url "${FLASHINFER_CU129_INDEX_URL}" \
159158
--extra-index-url "${PYTORCH_CU129_INDEX_URL}" \
159+
--extra-index-url "${VLLM_CU129_INDEX_URL}" \
160160
--index-strategy unsafe-best-match \
161161
--torch-backend cu129 \
162162
--overrides /tmp/safe-synthesizer-overrides.txt \
163163
--constraints /tmp/safe-synthesizer-constraints.txt \
164-
--requirements /tmp/safe-synthesizer-runtime.txt \
165-
--requirements /tmp/vllm-cu129.txt
164+
--requirements /tmp/safe-synthesizer-runtime.txt
166165

167166
COPY pyproject.toml uv.lock ./
168167
COPY packages/ packages/
@@ -179,9 +178,13 @@ RUN mkdir -p docs && \
179178
# Skip the `nemo-platform` wrapper wheel: it bundles every first-party plugin and
180179
# service, which drags unrelated source trees into this task image. The runtime
181180
# imports come from nemo-platform-sdk, nemo-platform-plugin, and nmp-common.
181+
# The runtime layer above installs CVE-patched cryptography/pyarrow; do not let
182+
# the workspace lock downgrade them during plugin sync.
182183
RUN --mount=type=cache,target=/root/.cache/uv \
183184
UV_CACHE_DIR=/root/.cache/uv uv sync --package nemo-safe-synthesizer-plugin --no-dev --no-editable --inexact \
184-
--no-install-package nemo-platform
185+
--no-install-package nemo-platform \
186+
--no-install-package cryptography \
187+
--no-install-package pyarrow
185188

186189
COPY docker/scripts/cve-cleanup.sh /bin/
187190
RUN bash /bin/cve-cleanup.sh

packages/nemo_platform/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ nemo-safe-synthesizer-plugin = [
351351
"gunicorn>=23.0.0",
352352
"httpx>=0.27.2",
353353
"nemo-platform-plugin",
354-
"nemo-safe-synthesizer==0.1.2",
354+
"nemo-safe-synthesizer==0.1.7",
355355
"pydantic[email]>=2.9.2",
356356
"pydantic-settings>=2.2.1",
357357
"python-multipart~=0.0.9",

plugins/nemo-safe-synthesizer/constraints.txt

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
# Vendored from https://github.com/NVIDIA-NeMo/Safe-Synthesizer/blob/v0.1.2/constraints.txt
2-
# on 2026-06-30. Local additions keep the AWS SDK packages aligned with
3-
# NeMo Platform's aiobotocore-compatible range.
1+
# Security floor constraints -- generated from [tool.uv] constraint-dependencies in pyproject.toml
2+
# Vendored from https://github.com/NVIDIA-NeMo/Safe-Synthesizer/blob/v0.1.7/constraints.txt
3+
# on 2026-07-10. Local additions keep pyarrow/cryptography on CVE-fixed
4+
# versions and the AWS SDK packages aligned with NeMo Platform's
5+
# aiobotocore-compatible range.
46
#
57
# Pass to pip/uv with: pip install <pkg> -c constraints.txt
68
# uv pip install <pkg> -c constraints.txt
7-
8-
# Security floor constraints -- generated from [tool.uv] constraint-dependencies in pyproject.toml
99
GitPython>=3.1.50
10-
PyJWT>=2.12.0
10+
PyJWT>=2.13.0
1111
Pygments>=2.20.0
12-
aiohttp>=3.13.4
12+
aiohttp>=3.14.0
1313
cbor2>=5.9.0
14-
cryptography>=46.0.7
14+
cryptography>=48.0.1,<49
1515
grpcio>=1.80.0
1616
idna>=3.15
1717
jsonpath-ng>=1.8.0
@@ -21,11 +21,14 @@ mistune>=3.2.1
2121
nbconvert>=7.17.1
2222
pandas<3
2323
pillow>=12.2.0
24+
pyarrow>=23.0.1,<24
2425
pymdown-extensions>=10.21.3
2526
python-dotenv>=1.2.2
2627
python-multipart>=0.0.27
2728
requests>=2.33.0
29+
starlette>=1.0.1
2830
tornado>=6.5.5
31+
urllib3>=2.7.0
2932

3033
# Runtime compatibility constraints.
3134
boto3>=1.40.46,<1.40.62

plugins/nemo-safe-synthesizer/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ dependencies = [
1212
"httpx>=0.27.2",
1313
"nemo-platform",
1414
"nemo-platform-plugin",
15-
"nemo-safe-synthesizer==0.1.2",
15+
"nemo-safe-synthesizer==0.1.7",
1616
"pydantic[email]>=2.9.2",
1717
"pydantic-settings>=2.2.1",
1818
"python-multipart~=0.0.9",

plugins/nemo-safe-synthesizer/src/nemo_safe_synthesizer_plugin/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class SafeSynthesizerConfig(NemoConfig):
3131
),
3232
)
3333
runtime_venv: str = ".nemo/safe-synthesizer-runtime"
34-
runtime_package: str = "nemo-safe-synthesizer[engine,cu129]==0.1.2"
34+
runtime_package: str = "nemo-safe-synthesizer[engine,cu129]==0.1.7"
3535
runtime_python_version: str = "3.11"
3636
runtime_python: str | None = None
3737
default_job_resource_memory_request: str = "16G"

plugins/nemo-safe-synthesizer/src/nemo_safe_synthesizer_plugin/runtime.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from __future__ import annotations
77

8-
import platform
98
import shutil
109
import subprocess
1110
from pathlib import Path
@@ -23,21 +22,7 @@
2322
RUNTIME_CONSTRAINTS_FILE = Path("plugins/nemo-safe-synthesizer/constraints.txt")
2423
FLASHINFER_CU129_INDEX_URL = "https://flashinfer.ai/whl/cu129"
2524
PYTORCH_CU129_INDEX_URL = "https://download.pytorch.org/whl/cu129"
26-
VLLM_CU129_VERSION = "0.20.0"
27-
28-
29-
def vllm_cu129_wheel() -> str:
30-
"""Return the direct vLLM CUDA 12.9 wheel URL for the current host."""
31-
machine = platform.machine().lower()
32-
if machine in {"amd64", "x86_64"}:
33-
arch = "x86_64"
34-
elif machine in {"aarch64", "arm64"}:
35-
arch = "aarch64"
36-
else:
37-
raise RuntimeError(f"Unsupported architecture for vLLM CUDA 12.9 wheel: {platform.machine()}")
38-
39-
wheel = f"vllm-{VLLM_CU129_VERSION}%2Bcu129-cp38-abi3-manylinux_2_31_{arch}.whl"
40-
return f"vllm @ https://github.com/vllm-project/vllm/releases/download/v{VLLM_CU129_VERSION}/{wheel}"
25+
VLLM_CU129_INDEX_URL = "https://wheels.vllm.ai/ee0da84ab9e04ac7610e28580af62c365e898389/cu129"
4126

4227

4328
def runtime_package_index_options(runtime_package: str) -> list[str]:
@@ -49,14 +34,18 @@ def runtime_package_index_options(runtime_package: str) -> list[str]:
4934
FLASHINFER_CU129_INDEX_URL,
5035
"--extra-index-url",
5136
PYTORCH_CU129_INDEX_URL,
37+
"--extra-index-url",
38+
VLLM_CU129_INDEX_URL,
5239
]
5340

5441

5542
def runtime_package_extra_requirements(runtime_package: str) -> list[str]:
5643
"""Return direct requirements needed by the selected runtime package."""
5744
if "cu129" not in runtime_package:
5845
return []
59-
return [vllm_cu129_wheel()]
46+
# Safe Synthesizer 0.1.7 declares its cu129 vLLM dependency directly; the
47+
# runtime only needs to add the vLLM wheel index above.
48+
return []
6049

6150

6251
def repo_root() -> Path:

plugins/nemo-safe-synthesizer/tests/unit/test_runtime.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,10 @@ def test_cuda_runtime_package_adds_cu129_sources():
5151
runtime.FLASHINFER_CU129_INDEX_URL,
5252
"--extra-index-url",
5353
runtime.PYTORCH_CU129_INDEX_URL,
54+
"--extra-index-url",
55+
runtime.VLLM_CU129_INDEX_URL,
5456
]
55-
assert runtime.runtime_package_extra_requirements(runtime_package) == [runtime.vllm_cu129_wheel()]
57+
assert runtime.runtime_package_extra_requirements(runtime_package) == []
5658

5759

5860
def test_non_cu129_runtime_package_does_not_add_cu129_sources():
@@ -90,7 +92,7 @@ def fake_run(command, **kwargs):
9092
assert "--extra-index-url" in calls[2][0]
9193
assert runtime.FLASHINFER_CU129_INDEX_URL in calls[2][0]
9294
assert runtime.PYTORCH_CU129_INDEX_URL in calls[2][0]
93-
assert runtime.vllm_cu129_wheel() in calls[2][0]
95+
assert runtime.VLLM_CU129_INDEX_URL in calls[2][0]
9496
assert str(tmp_path / "plugins/nemo-safe-synthesizer") not in calls[2][0]
9597
assert "nemo-safe-synthesizer[engine,cu129]" in calls[2][0]
9698
assert calls[3][0] == [

0 commit comments

Comments
 (0)