Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions agents/hermes/Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ ARG HERMES_SEMVER=0.19.0
ARG HERMES_TARBALL_SHA256=285f3fc134ff466a90065e1517801a68993733b807158ee8f32aa01613786990
ARG HERMES_NPM_INTEGRITY=sha512-+oVKG3lXbk2kEP+J6BXZjtmSBSaFfczIdOWQ9CUSTdTqq2uyHbk4p+kPyZ6MeGs56JU5qXzMNbqGKRVOQRGC1A==
ARG HERMES_UV_EXTRAS="anthropic messaging web pty mcp"
ARG UV_VERSION=0.11.8
ARG NODE_VERSION=24.18.1
ARG UV_VERSION=0.11.33

# build-essential: hermes-agent >= 0.16.0 ships npm dependencies that need a
# node-gyp native build during `npm ci`; the runtime Dockerfile purges build
Expand Down Expand Up @@ -220,12 +221,41 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
&& rm -rf /var/lib/apt/lists/* \
&& test -z "$(dpkg --audit)"

# The current node:24-trixie-slim digest still contains Node.js 24.16.0. Overlay
# the reviewed Node.js 24.18.1 release from nodejs.org so the Hermes runtime
# includes the security fixes without waiting for Docker Hub tag rotation.
# hadolint ignore=DL4006
RUN arch="$(dpkg --print-architecture)" \
&& case "$arch" in \
amd64) node_asset_arch="x64"; node_sha256="9f5eb6ac21845a66c493c91a253b1da32fd684e89e9b7202d4936982336be4ca" ;; \
arm64) node_asset_arch="arm64"; node_sha256="df224555a083b918e46260cc969838501b9f9a87140c1195e5b9597b56d5dae2" ;; \
*) echo "Unsupported architecture for Node.js: $arch" >&2; exit 1 ;; \
esac \
&& node_archive="/tmp/node-v${NODE_VERSION}-linux-${node_asset_arch}.tar.gz" \
&& curl --proto '=https' --tlsv1.2 -fsSL \
--retry 5 --retry-all-errors --retry-delay 2 --connect-timeout 15 --max-time 300 \
-o "$node_archive" \
"https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${node_asset_arch}.tar.gz" \
&& printf '%s %s\n' "$node_sha256" "$node_archive" | sha256sum -c - \
&& rm -rf \
/usr/local/include/node \
/usr/local/lib/node_modules/corepack \
/usr/local/lib/node_modules/npm \
/usr/local/share/doc/node \
/usr/local/share/man/man1/node.1 \
&& rm -f /usr/local/bin/corepack /usr/local/bin/node /usr/local/bin/npm /usr/local/bin/npx \
&& tar --extract --gzip --file "$node_archive" \
--directory /usr/local --strip-components=1 --no-same-owner \
&& rm -f "$node_archive" \
&& test "$(node --version)" = "v${NODE_VERSION}" \
&& test "$(npm --version)" = "11.16.0"

COPY scripts/lib/reviewed-npm-archive.mts /scripts/lib/reviewed-npm-archive.mts
COPY scripts/patch-bundled-npm-brace-expansion.mts /scripts/patch-bundled-npm-brace-expansion.mts
COPY scripts/patch-bundled-npm-tar.mts /scripts/patch-bundled-npm-tar.mts
COPY scripts/upgrade-bundled-npm.mts /scripts/upgrade-bundled-npm.mts

# npm 11.13.0 in the pinned Node 24 image bundles an affected node-tar copy.
# npm 11.16.0 in Node.js 24.18.1 bundles an affected node-tar copy.
# Patch that private package after curl is installed and before npm processes
# the reviewed npm archive.
RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \
Expand Down Expand Up @@ -381,7 +411,8 @@ RUN printf '%s\n' \
# writes under /opt/hermes. If a future Hermes tarball removes the lockfile,
# skip rather than doing a nondeterministic dependency resolve during image
# build.
RUN pip3 install --no-cache-dir --break-system-packages "uv==${UV_VERSION}"
RUN pip3 install --no-cache-dir --break-system-packages "uv==${UV_VERSION}" \
&& test "$(uv --version)" = "uv ${UV_VERSION}"
# Upstream tests are not part of the production runtime and can contain
# intentionally hostile security-test fixtures. Remove them in the extraction
# RUN so their bytes never enter a published image layer.
Expand Down Expand Up @@ -444,7 +475,7 @@ RUN set -eu; \
uv sync --frozen --no-dev "$@" --no-cache \
&& uv pip check --python /opt/hermes/.venv/bin/python \
&& /opt/hermes/.venv/bin/python -I -c \
"from importlib.metadata import version; expected = {'cryptography': '48.0.1', 'pillow': '12.3.0', 'starlette': '1.3.1'}; actual = {name: version(name) for name in expected}; assert actual == expected, actual" \
"from importlib.metadata import version; expected = {'cryptography': '48.0.1', 'mcp': '1.28.1', 'pillow': '12.3.0', 'starlette': '1.3.1', 'tornado': '6.5.7'}; actual = {name: version(name) for name in expected}; assert actual == expected, actual" \
&& npm ci --prefer-offline --no-audit --no-fund \
&& for ui_dir in ui-tui web; do \
if [ -f "${ui_dir}/package-lock.json" ]; then \
Expand Down
113 changes: 96 additions & 17 deletions agents/hermes/security-dependencies.patch

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion agents/langchain-deepagents-code/Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ RUN python3 -m venv --copies "$VIRTUAL_ENV" \
-r /tmp/deepagents-code-requirements.lock \
&& "$VIRTUAL_ENV/bin/pip3" check \
&& "$VIRTUAL_ENV/bin/python3" -I -c \
"from importlib.metadata import version; assert version('pillow') == '12.3.0', version('pillow')" \
"from importlib.metadata import version; expected = {'deepagents-code': '0.1.34', 'mcp': '1.28.1', 'pillow': '12.3.0', 'pyasn1': '0.6.4', 'uv': '0.11.33'}; actual = {name: version(name) for name in expected}; assert actual == expected, actual" \
&& ln -sf "$VIRTUAL_ENV/bin/dcode" /usr/local/bin/dcode \
&& ln -sf "$VIRTUAL_ENV/bin/deepagents-code" /usr/local/bin/deepagents-code \
&& rm -f /tmp/deepagents-code-requirements.lock \
Expand Down
32 changes: 17 additions & 15 deletions agents/langchain-deepagents-code/dependency-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,26 @@ This file records the reviewed dependency baseline for the Deep Agents Code sand
Update it whenever `requirements.lock` changes.

- Lockfile: `agents/langchain-deepagents-code/requirements.lock`
- Lockfile SHA-256: `d112ad4a01ff2b87211b1a10ecb98950e62d4bdffb37a122326af7b352250d25`
- Lockfile SHA-256: `b348f12ea2874c4240b523dc4e5814dce58893cd70de5ebbd74d313cbf6cc1e1`
- Audit command: `uv tool run --python 3.13 pip-audit -r agents/langchain-deepagents-code/requirements.lock --progress-spinner off --disable-pip`
- Audit date: 2026-07-29
- Targeted audit result: `Pillow 12.3.0 has no known vulnerabilities`
- Complete-lock audit result: `6 records in 3 unrelated packages`
- Audit date: 2026-07-30
- Targeted audit result: `uv 0.11.33, MCP 1.28.1, Pillow 12.3.0, and pyasn1 0.6.4 have no known vulnerabilities`
- Complete-lock audit result: `2 duplicate records in 1 unrelated package`

The Dockerfile installs this lockfile with `pip3 install --require-hashes`, so this review covers the exact package versions selected for the managed image install.
The lock now selects `Pillow==12.3.0` instead of the transitive `12.2.0`
resolution, removing the image-parser advisories in this remediation scope.
The image build runs `pip3 check` and asserts the exact installed Pillow
version before publishing.

The complete point-in-time audit also reports one record for `mcp==1.28.0`,
three for `pyasn1==0.6.3`, and two duplicate database records for
`setuptools==82.0.1`. These newly published records are not introduced by the
Pillow-only lock regeneration and remain visible for a separate
dependency-lifecycle review; this review does not claim the complete lock is
vulnerability-free.
The lock now selects `uv==0.11.33`, `mcp==1.28.1`, `Pillow==12.3.0`, and
`pyasn1==0.6.4`. The direct MCP and pyasn1 requirements are temporary,
hash-locked constraints for the released Deep Agents Code `0.1.34` graph.
Deep Agents Code `0.1.45` and later contain both dependency fixes, but their hook
boundary has changed. Remove the temporary direct constraints only as part of a
separately validated semantic migration to `>=0.1.45` that preserves NemoClaw's
managed runtime hooks.

The image build runs `pip3 check` and asserts all five installed package
versions, including Deep Agents Code itself, before publishing. The complete
point-in-time audit now reports only two duplicate database records for
`setuptools==82.0.1`; that record is outside the Critical/High remediation
scope. This review does not claim the complete lock is vulnerability-free.

## Managed `fetch_url` Proxy Adapter

Expand Down
6 changes: 5 additions & 1 deletion agents/langchain-deepagents-code/requirements.in
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
uv==0.11.15
uv==0.11.33
deepagents-code[nvidia,openrouter]==0.1.34
nemo-relay[langgraph]==0.4.0
# Fix the image parser advisories reported against the transitive 12.2.0 pin.
pillow==12.3.0
# Keep the managed MCP transport on the first release with Host/Origin validation.
mcp==1.28.1
# Fix the transitive ASN.1 decoder resource-exhaustion advisories.
pyasn1==0.6.4
57 changes: 30 additions & 27 deletions agents/langchain-deepagents-code/requirements.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1311,10 +1311,11 @@ markdownify==1.2.2 \
--hash=sha256:3f02d3cc52714084d6e589f70397b6fc9f2f3a8531481bf35e8cc39f975e186a \
--hash=sha256:b274f1b5943180b031b699b199cbaeb1e2ac938b75851849a31fd0c3d6603d09
# via deepagents-code
mcp==1.28.0 \
--hash=sha256:559d3f9943674cafbe5744c5d3794f3237e8b47f9bbc58e20c0fad680d8487c2 \
--hash=sha256:9c1e7cf3a9125557e418ecd4fed8e9adddce81b0dfdae4d6601d700f5beb71a4
mcp==1.28.1 \
--hash=sha256:2726bca5e7193f61c5dde8b12500a6de2d9acf6d1a1c0be9e8c2e706437991df \
--hash=sha256:d51e36a5f5644faea4f85ea649bfffa6bc6c26770d42798ad6a3de3d2ba69683
# via
# -r agents/langchain-deepagents-code/requirements.in
# deepagents-code
# langchain-mcp-adapters
mdit-py-plugins==0.6.1 \
Expand Down Expand Up @@ -1908,10 +1909,12 @@ protobuf==6.33.6 \
# grpcio-tools
# langgraph-api
# opentelemetry-proto
pyasn1==0.6.3 \
--hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \
--hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde
# via pyasn1-modules
pyasn1==0.6.4 \
--hash=sha256:9c447d8431c947fe4c8febc4ed9e760bc29011a5b01e5c74b67025bd9fb8ce81 \
--hash=sha256:deda9277cfd454080ec40b207fb6df82206a3a2688735233cdcd8d3d565f088b
# via
# -r agents/langchain-deepagents-code/requirements.in
# pyasn1-modules
pyasn1-modules==0.4.2 \
--hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \
--hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6
Expand Down Expand Up @@ -2840,26 +2843,26 @@ uuid-utils==0.16.2 \
# langchain-core
# langgraph-api
# langsmith
uv==0.11.15 \
--hash=sha256:0ed920e896b2fd13a35031707e307e42fbb2681458b967440a17272d86d49137 \
--hash=sha256:40ff67e3f8e8a7533781a2e892a534975a93acb83ea35460e64e7b2bf2111774 \
--hash=sha256:41d907611f3e6a13262807fd7f0a17849f76285ca80f536f6b3943732bdc6656 \
--hash=sha256:49dc6ed70bff00937384f96cdc4b1a4742d18e5504ec2c4a1214dba2dee5687a \
--hash=sha256:4f39426a13dee24897aed60c4b98058c66f18bd983885ac5f4a54a04b24fbddf \
--hash=sha256:68c1e62d4b78578b90b833553286b65d6a7e327537716441068583ba652ec4f5 \
--hash=sha256:755f959ec6a2fd8ccb6ee76ad90ab759d2eb1f4797444078645dd1ee4bca92d6 \
--hash=sha256:83b04ab49514a0a761ffedb36a748ee81f87746671e72088e5f32c9585e5f1a9 \
--hash=sha256:8e2da3076761086a5b76869c3f38ef0509c836046ef41ddd19485dfd7271dca9 \
--hash=sha256:98edf1bdaf82447014852051d93e3ee95012509c567bf057fd117e6bdbd9a807 \
--hash=sha256:9accae33619a9166e5c48531deb455d672cfb89f9357a00975e669c76b0bd49f \
--hash=sha256:adb9a89352539fdd8f7cd5f9966cf9f94fc5b98e0ccdf5003a04123dc6423bec \
--hash=sha256:b6cae61f737be075b90be9e3f07d961072aed7019f4c9b8ed5c5d41c4d6cade3 \
--hash=sha256:be8f76d25bcf4c92bb384240ac1bf9aa7f51063d0bdeca4c9cf0ec3ed8b145e0 \
--hash=sha256:c0cf52cd6d50bb9e05e2d968f45f80761107e4cbc8d4a26d9758f9d8274aaec1 \
--hash=sha256:c6463a299ed7e6b5a800ed6f108af8e1588352629424133ddef7572b0e1e1118 \
--hash=sha256:cc3915ab291a1ecaf31de05f5d8bd70d09c66fe9911a53f70d9efa62ff0dbd8a \
--hash=sha256:e3b68f8bf1a4568710f77e5bda9182ce7682811d89a8e7468c22460e032b234d \
--hash=sha256:f9f4fbbf4fe485522054f3c7496c6e8e932d6436e4200ff3daf718db0b7c7bd5
uv==0.11.33 \
--hash=sha256:2a8506f558e08498c0d80857c356452d14048eddfcc7bc20ec9f201b3011eaaf \
--hash=sha256:3242c8bc708b75fb72687c9a24f0e6f47c2004a3d82d32a81b06e17822708c28 \
--hash=sha256:36a98c68ba5c3bb59469414f54aaf00bd3134a647ca34509bc53d133ed8e0b5d \
--hash=sha256:3cb5b325c58a9ee5febfedf4895e0c48cc7d22d801d1b23a4b8335f16508d0da \
--hash=sha256:521229afa69ad5f57127de800120cb2bea1ac729a05a0851aaf920124f8edf66 \
--hash=sha256:686ed8c8d9e76eb9259e7f7db627ea836420d9a5e013b169c41398bcd28ee948 \
--hash=sha256:70826563c7617efbf7244946354628253e4ea63d72cb1d35b98be4896c4530fd \
--hash=sha256:71d00a28beb3924c593ba7ec248263679ae1f7c0f63a8cccc75e7d11ccb2adce \
--hash=sha256:8017991a398a55d177c33ecdb29beb33e7b53969921183e4681e3e5b278d73c2 \
--hash=sha256:923874411bc0bbf5d1de16cdb14a7800d696d6c6e774eb1b202966243c6d507b \
--hash=sha256:94fb388a86cf6c2f2610b427f1bf0897bc0f2771a869da41433e17f7d21a1a41 \
--hash=sha256:9542178978b0b6f16a7ae99e55aca039f493a1edb373a15d7993eab80a28615a \
--hash=sha256:a4411bf854f5fe3d4b78d37dd2e4b84e0b99fbb0bd185de1511a8515404e04a8 \
--hash=sha256:ab9ee61ed9c7c843b52795a96733e109cec831cd3250d73d291bccbb90a81999 \
--hash=sha256:ad74bd02a236417df9766b913c2613a7c3db0ef071c4c2390d28e5005be3e4b2 \
--hash=sha256:c1ca9b0b51cd89310f87f1fc0bf9d9c6fdb64be516fe3e409817662ec3d9378f \
--hash=sha256:d629531a4e8f7cd76d861ec2e0035faef2675036a084d0a5b35dad5025ec62aa \
--hash=sha256:e00f371e1affe3fac88f9f1afab31139c8199ecf8df7b1a37554f83629fd7eab \
--hash=sha256:f4196584a7f7fbfef3dde1b1a0454c174399bd96071cdfb066c263a798a4524e
# via -r agents/langchain-deepagents-code/requirements.in
uvicorn==0.49.0 \
--hash=sha256:ba3d14c3ee7e41c6c654c46c9eb489d33213cdd30aa1696eab1374337c13f68f \
Expand Down
Loading
Loading