Skip to content
Closed
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
429 changes: 402 additions & 27 deletions .github/workflows/base-image.yaml

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,8 @@ RUN set -eu; \
"vim-tiny=2:9.2.0782-1" \
"libssh2-1t64=1.11.1-1+deb13u1+nemoclaw1" \
"nemoclaw-python3.13-htmlparser-fix=3.13.5-2+deb13u4+nemoclaw1" \
"perl-base=5.44.0-1nemoclaw1" \
"perl=5.44.0-1nemoclaw1" \
| cmp -s - "$security_inventory"; \
test "$(dpkg-query -W -f='${Version}' libexpat1)" = "2.8.2-1"; \
test "$(dpkg-query -W -f='${Version}' libonig5)" = "6.9.9-1+b1"; \
Expand All @@ -1749,6 +1751,9 @@ RUN set -eu; \
test "$(dpkg-query -W -f='${Version}' vim-tiny)" = "2:9.2.0782-1"; \
test "$(dpkg-query -W -f='${Version}' libssh2-1t64)" = "1.11.1-1+deb13u1+nemoclaw1"; \
test "$(dpkg-query -W -f='${Version}' nemoclaw-python3.13-htmlparser-fix)" = "3.13.5-2+deb13u4+nemoclaw1"; \
test "$(dpkg-query -W -f='${Version}' perl-base)" = "5.44.0-1nemoclaw1"; \
test "$(dpkg-query -W -f='${Version}' perl)" = "5.44.0-1nemoclaw1"; \
test "$(perl -e 'print $^V')" = "v5.44.0"; \
ldd /usr/bin/jq | grep -Eq 'libonig[.]so[.]5'; \
test "$(jq --version)" = "jq-1.8.2"; \
printf '%s\n' '{"sandbox":"healthy"}' | jq -e '.sandbox == "healthy"' >/dev/null; \
Expand Down
115 changes: 16 additions & 99 deletions Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -78,117 +78,27 @@ COPY scripts/security/patches/python3.13-htmlparser-cve-2026-15308.patch /script

RUN bash /scripts/security/build-native-security-packages.sh /out

# Debian trixie has not published a Perl package containing the upstream
# fixes for CVE-2026-12087, CVE-2026-13221, and CVE-2026-57433. Build the
# fixed upstream release as native Debian packages so dpkg dependencies and
# vulnerability inventory both describe the runtime that is actually used.
FROM node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba AS perl-builder
# Debian trixie has not published a Perl package containing the reviewed
# upstream fixes. Build the fixed release as native Debian packages so dpkg
# dependencies and vulnerability inventory describe the executed runtime.
FROM native-security-builder AS perl-builder

ARG PERL_VERSION
ARG PERL_SHA256
ARG PERL_PACKAGE_REVISION

COPY --from=native-security-builder /out /tmp/security-packages
COPY scripts/security/build-perl-security-packages.sh /scripts/security/build-perl-security-packages.sh

RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential=12.12 \
ca-certificates=20250419 \
curl=8.14.1-2+deb13u4 \
netbase=6.5 \
xz-utils=5.8.1-1+deb13u1 \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /tmp/perl-source

# Pin the reviewed d_syscallproto result for trixie's libc so both native
# architectures use the same known declaration instead of relying on a
# Configure probe that previously returned a false negative under QEMU.
# Remove this override only after the pinned base image and Perl release report
# d_syscallproto=define from native Configure probes on amd64 and arm64.
# Perl's test_harness runs the same upstream suite while TEST_JOBS lets its TAP
# scheduler use each native runner efficiently instead of serializing every
# script in QEMU.
# ExtUtils::Constant's test recursively invokes make and produced an incomplete
# TAP plan when it overlapped another test locally, so run it alone first and
# exclude exactly that already-passed file from the parallel pass.
# Remove this split only after the unsplit parallel harness passes in two
# consecutive amd64 and arm64 base-image builds; keep the selection-equivalence
# check below until that removal condition is met.
RUN curl --proto '=https' --tlsv1.2 -fsSL \
--retry 5 --retry-all-errors --retry-delay 2 --connect-timeout 15 --max-time 120 \
-o /tmp/perl.tar.xz "https://www.cpan.org/src/5.0/perl-${PERL_VERSION}.tar.xz" \
&& printf '%s %s\n' "${PERL_SHA256}" /tmp/perl.tar.xz > /tmp/perl.sha256 \
&& sha256sum -c /tmp/perl.sha256 \
&& tar -xJf /tmp/perl.tar.xz -C /tmp/perl-source --strip-components=1 \
&& ./Configure -des \
-Dprefix=/usr \
-Dvendorprefix=/usr \
-Dsiteprefix=/usr/local \
-Dusethreads \
-Duse64bitall \
-Dd_syscallproto=define \
-Dman1dir=none \
-Dman3dir=none \
&& make -j"$(nproc)" \
&& make test_prep \
&& env -C t PERL_TEST_HARNESS_ASAP=1 ./perl harness -dumptests \
> /tmp/perl-tests-full \
&& env -C t ./perl harness -dumptests \
../cpan/ExtUtils-Constant/t/Constant.t \
> /tmp/perl-tests-serial \
&& env -C t PERL_TEST_HARNESS_ASAP=1 ./perl harness -dumptests \
'--nre=^[.][.]/cpan/ExtUtils-Constant/t/Constant[.]t$' \
> /tmp/perl-tests-parallel \
&& sort /tmp/perl-tests-full > /tmp/perl-tests-full.sorted \
&& sort /tmp/perl-tests-serial /tmp/perl-tests-parallel \
> /tmp/perl-tests-combined.sorted \
&& cmp /tmp/perl-tests-full.sorted /tmp/perl-tests-combined.sorted \
&& test "$(grep -Fxc \
'cpan/ExtUtils-Constant/t/Constant.t' \
/tmp/perl-tests-combined.sorted)" -eq 1 \
&& TEST_JOBS=1 TEST_ARGS='../cpan/ExtUtils-Constant/t/Constant.t' make test_harness \
&& TEST_JOBS="$(nproc)" PERL_TEST_HARNESS_ASAP=1 \
TEST_ARGS='--nre=^[.][.]/cpan/ExtUtils-Constant/t/Constant[.]t$' \
make -j"$(nproc)" test_harness \
&& make install DESTDIR=/tmp/perl-root

RUN package_version="${PERL_VERSION}-${PERL_PACKAGE_REVISION}" \
&& architecture="$(dpkg --print-architecture)" \
&& mkdir -p /tmp/perl-root/DEBIAN /tmp/perl-meta/DEBIAN \
&& printf '%s\n' \
'Package: perl-base' \
"Version: ${package_version}" \
"Architecture: ${architecture}" \
'Essential: yes' \
'Priority: required' \
'Section: perl' \
'Multi-Arch: allowed' \
'Maintainer: NVIDIA NemoClaw Maintainers' \
"Provides: libperl5.40 (= ${package_version}), perl-modules-5.40 (= ${package_version})" \
'Conflicts: libperl5.40, perl-modules-5.40' \
"Breaks: perl (<< ${package_version})" \
"Replaces: libperl5.40, perl-modules-5.40, perl (<< ${package_version})" \
'Description: Perl 5 language interpreter built for the NemoClaw sandbox' \
> /tmp/perl-root/DEBIAN/control \
&& printf '%s\n' \
'Package: perl' \
"Version: ${package_version}" \
"Architecture: ${architecture}" \
'Priority: standard' \
'Section: perl' \
'Multi-Arch: allowed' \
"Depends: perl-base (= ${package_version})" \
'Maintainer: NVIDIA NemoClaw Maintainers' \
'Description: Perl 5 language interpreter metapackage for the NemoClaw sandbox' \
> /tmp/perl-meta/DEBIAN/control \
&& dpkg-deb --build --root-owner-group \
/tmp/perl-root /tmp/security-packages/perl-base.deb \
&& dpkg-deb --build --root-owner-group \
/tmp/perl-meta /tmp/security-packages/perl.deb
RUN bash /scripts/security/build-perl-security-packages.sh \
/out "${PERL_VERSION}" "${PERL_SHA256}" "${PERL_PACKAGE_REVISION}"

FROM node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba

COPY --from=perl-builder /tmp/security-packages /tmp/nemoclaw-native-security
COPY --from=perl-builder /out /tmp/nemoclaw-native-security

# OpenShell blocks the link-local EC2 Instance Metadata Service. Keep AWS SDK
# credential chains from attempting an impossible metadata discovery path.
Expand Down Expand Up @@ -317,7 +227,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
"nemoclaw-python3.13-htmlparser-fix=3.13.5-2+deb13u4+nemoclaw1" \
> /usr/local/share/nemoclaw/security-packages.txt \
&& chown root:root /usr/local/share/nemoclaw/security-packages.txt \
&& chmod 0444 /usr/local/share/nemoclaw/security-packages.txt \
&& chmod 0644 /usr/local/share/nemoclaw/security-packages.txt \
&& rm -rf "$security_deb_dir" \
&& rm -rf /var/lib/apt/lists/* \
&& ln -s /usr/bin/python3 /usr/local/bin/python
Expand All @@ -328,6 +238,8 @@ RUN apt-get update \
/tmp/nemoclaw-native-security/perl.deb \
&& rm -rf /tmp/nemoclaw-native-security \
&& rm -rf /var/lib/apt/lists/* \
&& test "$(dpkg-query -W -f='${Version}' perl-base)" = "5.44.0-1nemoclaw1" \
&& test "$(dpkg-query -W -f='${Version}' perl)" = "5.44.0-1nemoclaw1" \
&& test "$(perl -e 'print $^V')" = "v5.44.0" \
&& test "$(perl -MSocket -e 'print Socket->VERSION')" = "2.041" \
&& test "$(perl -MStorable -e 'print Storable->VERSION')" = "3.41" \
Expand All @@ -339,6 +251,11 @@ RUN apt-get update \
'eval { pack_ip_mreq_source("\0" x 4, "\0" x 3) }; die "short source accepted" unless $@ =~ /Bad arg length/' \
&& perl -e \
'my $x = join "|", "aaa".."mzz"; my $y = join "|", "naa".."zzz"; use re "Debug"; "fnord" =~ m/(?:$x)|(?:$y)/' \
&& printf '%s\n' \
"perl-base=5.44.0-1nemoclaw1" \
"perl=5.44.0-1nemoclaw1" \
>> /usr/local/share/nemoclaw/security-packages.txt \
&& chmod 0444 /usr/local/share/nemoclaw/security-packages.txt \
&& git --version \
&& test -z "$(dpkg --audit)"

Expand Down
5 changes: 5 additions & 0 deletions agents/hermes/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,8 @@ RUN set -eu; \
"vim-tiny=2:9.2.0782-1" \
"libssh2-1t64=1.11.1-1+deb13u1+nemoclaw1" \
"nemoclaw-python3.13-htmlparser-fix=3.13.5-2+deb13u4+nemoclaw1" \
"perl-base=5.44.0-1nemoclaw1" \
"perl=5.44.0-1nemoclaw1" \
| cmp -s - "$security_inventory"; \
test "$(dpkg-query -W -f='${Version}' libexpat1)" = "2.8.2-1"; \
test "$(dpkg-query -W -f='${Version}' libonig5)" = "6.9.9-1+b1"; \
Expand All @@ -1197,6 +1199,9 @@ RUN set -eu; \
test "$(dpkg-query -W -f='${Version}' vim-tiny)" = "2:9.2.0782-1"; \
test "$(dpkg-query -W -f='${Version}' libssh2-1t64)" = "1.11.1-1+deb13u1+nemoclaw1"; \
test "$(dpkg-query -W -f='${Version}' nemoclaw-python3.13-htmlparser-fix)" = "3.13.5-2+deb13u4+nemoclaw1"; \
test "$(dpkg-query -W -f='${Version}' perl-base)" = "5.44.0-1nemoclaw1"; \
test "$(dpkg-query -W -f='${Version}' perl)" = "5.44.0-1nemoclaw1"; \
test "$(perl -e 'print $^V')" = "v5.44.0"; \
ldd /usr/bin/jq | grep -Eq 'libonig[.]so[.]5'; \
test "$(jq --version)" = "jq-1.8.2"; \
printf '%s\n' '{"sandbox":"healthy"}' | jq -e '.sandbox == "healthy"' >/dev/null; \
Expand Down
42 changes: 40 additions & 2 deletions agents/hermes/Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
# 6. New .hermes subdirectory — add mkdir/chmod below
# ────────────────────────────────────────────────────────────────

ARG PERL_VERSION=5.44.0
ARG PERL_SHA256=505cf43912e9480495c344c70260452e32aa2a73c546a026b3f100053b23ce91
ARG PERL_PACKAGE_REVISION=1nemoclaw1

FROM node:24-trixie-slim@sha256:05c08ce4291e9a58f59456a7985176defb12cdd42271f35ff81a3e167ea61d4c AS native-security-builder

RUN apt-get update && apt-get install -y --no-install-recommends \
Expand All @@ -38,9 +42,24 @@ COPY scripts/security/patches/python3.13-htmlparser-cve-2026-15308.patch /script

RUN bash /scripts/security/build-native-security-packages.sh /out

FROM native-security-builder AS perl-builder

ARG PERL_VERSION
ARG PERL_SHA256
ARG PERL_PACKAGE_REVISION

COPY scripts/security/build-perl-security-packages.sh /scripts/security/build-perl-security-packages.sh

RUN apt-get update && apt-get install -y --no-install-recommends \
netbase=6.5 \
&& rm -rf /var/lib/apt/lists/*

RUN bash /scripts/security/build-perl-security-packages.sh \
/out "${PERL_VERSION}" "${PERL_SHA256}" "${PERL_PACKAGE_REVISION}"

FROM node:24-trixie-slim@sha256:05c08ce4291e9a58f59456a7985176defb12cdd42271f35ff81a3e167ea61d4c

COPY --from=native-security-builder /out /tmp/nemoclaw-native-security
COPY --from=perl-builder /out /tmp/nemoclaw-native-security

ENV DEBIAN_FRONTEND=noninteractive

Expand Down Expand Up @@ -145,6 +164,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
"$security_deb_dir/vim-tiny.deb" \
/tmp/nemoclaw-native-security/libssh2-1t64.deb \
/tmp/nemoclaw-native-security/nemoclaw-python3.13-htmlparser-fix.deb \
&& apt-get install -y --no-install-recommends \
/tmp/nemoclaw-native-security/perl-base.deb \
/tmp/nemoclaw-native-security/perl.deb \
&& test "$(dpkg-query -W -f='${Version}' perl-base)" = "5.44.0-1nemoclaw1" \
&& test "$(dpkg-query -W -f='${Version}' perl)" = "5.44.0-1nemoclaw1" \
&& test "$(dpkg-query -W -f='${Version}' libexpat1)" = "2.8.2-1" \
&& test "$(dpkg-query -W -f='${Version}' libonig5)" = "6.9.9-1+b1" \
&& test "$(dpkg-query -W -f='${Version}' libjq1)" = "1.8.2-1" \
Expand All @@ -164,6 +188,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
&& python3 -c "import sys; from pathlib import Path; import html.parser; Path(html.parser.__file__).resolve() == Path('/usr/lib/python3.13/html/parser.py').resolve() or sys.exit('html.parser loaded from an unexpected path'); from html.parser import HTMLParser; p=HTMLParser(); [p.feed('') for _ in range(20000)]; p._pending == [] or sys.exit('empty feeds accumulated pending entries'); p.feed('<!--'); [p.feed('a' * 64) for _ in range(20000)]; p.feed('-->'); p.close(); p.rawdata == '' or sys.exit('incremental parsing retained raw data')" \
&& python3 -c "import ctypes, sys; lib=ctypes.CDLL('libssh2.so.1'); lib.libssh2_version.restype=ctypes.c_char_p; lib.libssh2_version(0) == b'1.11.1' or sys.exit('unexpected libssh2 runtime version')" \
&& vim.tiny --version | head -n 1 | grep -Eq '^VIM - Vi IMproved 9[.]2 ' \
&& test "$(perl -e 'print $^V')" = "v5.44.0" \
&& test "$(perl -MSocket -e 'print Socket->VERSION')" = "2.041" \
&& test "$(perl -MStorable -e 'print Storable->VERSION')" = "3.41" \
&& test "$(perl -MHTTP::Tiny -e 'print HTTP::Tiny->VERSION')" = "0.096" \
&& test "$(perl -MIO::Compress::Base -e 'print IO::Compress::Base->VERSION')" = "2.223" \
&& test "$(perl -MIO::Uncompress::Unzip -e 'print IO::Uncompress::Unzip->VERSION')" = "2.223" \
&& test "$(perl -MFile::GlobMapper -e 'print File::GlobMapper->VERSION')" = "1.001" \
&& perl -MSocket=pack_ip_mreq_source -e \
'eval { pack_ip_mreq_source("\0" x 4, "\0" x 3) }; die "short source accepted" unless $@ =~ /Bad arg length/' \
&& perl -e \
'my $x = join "|", "aaa".."mzz"; my $y = join "|", "naa".."zzz"; use re "Debug"; "fnord" =~ m/(?:$x)|(?:$y)/' \
&& install -d -o root -g root -m 0755 /usr/local/share/nemoclaw \
&& printf '%s\n' \
"architecture=$arch" \
Expand All @@ -175,12 +210,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
"vim-tiny=2:9.2.0782-1" \
"libssh2-1t64=1.11.1-1+deb13u1+nemoclaw1" \
"nemoclaw-python3.13-htmlparser-fix=3.13.5-2+deb13u4+nemoclaw1" \
"perl-base=5.44.0-1nemoclaw1" \
"perl=5.44.0-1nemoclaw1" \
> /usr/local/share/nemoclaw/security-packages.txt \
&& chown root:root /usr/local/share/nemoclaw/security-packages.txt \
&& chmod 0444 /usr/local/share/nemoclaw/security-packages.txt \
&& rm -rf /tmp/nemoclaw-native-security \
&& rm -rf "$security_deb_dir" \
&& rm -rf /var/lib/apt/lists/*
&& rm -rf /var/lib/apt/lists/* \
&& test -z "$(dpkg --audit)"

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
Expand Down
5 changes: 5 additions & 0 deletions agents/langchain-deepagents-code/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ RUN set -eu; \
"vim-tiny=2:9.2.0782-1" \
"libssh2-1t64=1.11.1-1+deb13u1+nemoclaw1" \
"nemoclaw-python3.13-htmlparser-fix=3.13.5-2+deb13u4+nemoclaw1" \
"perl-base=5.44.0-1nemoclaw1" \
"perl=5.44.0-1nemoclaw1" \
| cmp -s - "$security_inventory"; \
test "$(dpkg-query -W -f='${Version}' libexpat1)" = "2.8.2-1"; \
test "$(dpkg-query -W -f='${Version}' libonig5)" = "6.9.9-1+b1"; \
Expand All @@ -248,6 +250,9 @@ RUN set -eu; \
test "$(dpkg-query -W -f='${Version}' vim-tiny)" = "2:9.2.0782-1"; \
test "$(dpkg-query -W -f='${Version}' libssh2-1t64)" = "1.11.1-1+deb13u1+nemoclaw1"; \
test "$(dpkg-query -W -f='${Version}' nemoclaw-python3.13-htmlparser-fix)" = "3.13.5-2+deb13u4+nemoclaw1"; \
test "$(dpkg-query -W -f='${Version}' perl-base)" = "5.44.0-1nemoclaw1"; \
test "$(dpkg-query -W -f='${Version}' perl)" = "5.44.0-1nemoclaw1"; \
test "$(perl -e 'print $^V')" = "v5.44.0"; \
ldd /usr/bin/jq | grep -Eq 'libonig[.]so[.]5'; \
test "$(jq --version)" = "jq-1.8.2"; \
printf '%s\n' '{"sandbox":"healthy"}' | jq -e '.sandbox == "healthy"' >/dev/null; \
Expand Down
Loading
Loading