Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c96de62
fix(security): remediate OpenClaw transitive dependencies
jyaunches Jul 21, 2026
b3fb226
fix(security): complete OpenClaw transitive remediation
jyaunches Jul 21, 2026
a98e9b9
test(security): keep remediation fixture linear
jyaunches Jul 21, 2026
223aea5
test(security): cover remediated plugin archives
jyaunches Jul 21, 2026
c9aa63c
fix(security): preserve OpenClaw global dependencies
jyaunches Jul 21, 2026
f85e877
test(security): cover installed dependency smoke check
jyaunches Jul 21, 2026
6752f3e
fix(onboard): stabilize authoritative rebuilds
cjagwani Jul 21, 2026
e56fab9
test(e2e): budget authoritative base rebuilds
jyaunches Jul 21, 2026
4490f96
test(e2e): provision swap for Hermes rebuilds
jyaunches Jul 21, 2026
1bdd32c
test(e2e): repair legacy Hermes fixture permissions
jyaunches Jul 21, 2026
6f4158e
test(e2e): run Hermes fixture commands outside Landlock
cjagwani Jul 21, 2026
fe649b0
test(e2e): simplify legacy Hermes fixture image
jyaunches Jul 21, 2026
c9396cf
test(e2e): expand Hermes rebuild swap
jyaunches Jul 21, 2026
4430f7b
test(e2e): preserve Hermes runtime state path
jyaunches Jul 21, 2026
1acc180
test(e2e): pin Hermes kanban database
jyaunches Jul 21, 2026
37929a3
fix(state): fail closed on sqlite backup errors
jyaunches Jul 21, 2026
d24912a
fix(state): isolate sqlite backup runtime
jyaunches Jul 21, 2026
33d10a7
fix(state): use system Python for SQLite snapshots
jyaunches Jul 21, 2026
b26cf68
ci(e2e): retry trusted PR gate
jyaunches Jul 21, 2026
3644f98
test(e2e): provision trusted Hermes rebuild swap
jyaunches Jul 21, 2026
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
1 change: 1 addition & 0 deletions .github/workflows/base-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ on:
- "agents/openclaw/mcporter-runtime/package-lock.json"
# Dockerfile.base validates min_openclaw_version from this file at build time.
- "nemoclaw-blueprint/blueprint.yaml"
- "scripts/lib/openclaw-npm-remediation.mts"
- "scripts/lib/reviewed-npm-archive.mts"
- "scripts/lib/sandbox-rlimits.sh"
workflow_dispatch:
Expand Down
18 changes: 15 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ COPY agents/openclaw/mcporter-runtime/package-lock.json /usr/local/lib/nemoclaw/
COPY agents/openclaw/wechat-runtime/package.json /usr/local/lib/nemoclaw/wechat-runtime/package.json
COPY agents/openclaw/wechat-runtime/package-lock.json /usr/local/lib/nemoclaw/wechat-runtime/package-lock.json
COPY scripts/lib/reviewed-npm-archive.mts /scripts/lib/reviewed-npm-archive.mts
COPY scripts/lib/openclaw-npm-remediation.mts /scripts/lib/openclaw-npm-remediation.mts

# 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 @@ -287,6 +288,8 @@ RUN set -eu; \
if [ -z "$EXPECTED_INTEGRITY" ]; then \
echo "ERROR: OpenClaw ${OPENCLAW_VERSION} has no committed npm integrity pin" >&2; exit 1; \
fi; \
OPENCLAW_RECIPE='ignore-scripts+reviewed-lifecycle-v1'; \
if [ "$OPENCLAW_VERSION" = "2026.6.10" ]; then OPENCLAW_RECIPE='ignore-scripts+reviewed-lifecycle+transitive-remediation-v1'; fi; \
MCPORTER_EXPECTED_INTEGRITY=""; \
MCPORTER_EXPECTED_TARBALL=""; \
if [ "$MCPORTER_VERSION" = "0.7.3" ]; then MCPORTER_EXPECTED_INTEGRITY="$MCPORTER_0_7_3_INTEGRITY"; MCPORTER_EXPECTED_TARBALL="$MCPORTER_0_7_3_TARBALL"; fi; \
Expand All @@ -307,7 +310,7 @@ RUN set -eu; \
"package=openclaw@${OPENCLAW_VERSION}" \
"integrity=${EXPECTED_INTEGRITY}" \
"tarball=${EXPECTED_TARBALL}" \
'recipe=ignore-scripts+reviewed-lifecycle-v1' \
"recipe=${OPENCLAW_RECIPE}" \
"mcporter-package=mcporter@${MCPORTER_VERSION}" \
"mcporter-integrity=${MCPORTER_EXPECTED_INTEGRITY}" \
"mcporter-tarball=${MCPORTER_EXPECTED_TARBALL}" \
Expand Down Expand Up @@ -337,10 +340,16 @@ RUN set -eu; \
echo "ERROR: Base image has OpenClaw $CUR_VER, which is newer than reviewed target $OPENCLAW_VERSION" >&2; exit 1; \
else \
echo "INFO: Base image OpenClaw $CUR_VER lacks exact reviewed provenance; installing $OPENCLAW_VERSION"; \
OPENCLAW_PACK_PATH="$(node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts \
OPENCLAW_SOURCE_PACK_PATH="$(node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts \
--package-spec "openclaw@${OPENCLAW_VERSION}" --integrity "$EXPECTED_INTEGRITY" \
--tarball-url "$EXPECTED_TARBALL" --label "OpenClaw ${OPENCLAW_VERSION}")"; \
OPENCLAW_PACK_DIR="$(dirname "$OPENCLAW_PACK_PATH")"; \
OPENCLAW_PACK_DIR="$(dirname "$OPENCLAW_SOURCE_PACK_PATH")"; \
OPENCLAW_PACK_PATH="$OPENCLAW_SOURCE_PACK_PATH"; \
if [ "$OPENCLAW_VERSION" = "2026.6.10" ]; then \
OPENCLAW_PACK_PATH="$(node --experimental-strip-types /scripts/lib/openclaw-npm-remediation.mts \
--archive "$OPENCLAW_SOURCE_PACK_PATH" --package-spec "openclaw@${OPENCLAW_VERSION}" \
--working-directory "$OPENCLAW_PACK_DIR")"; \
fi; \
# npm 10's atomic-move install can hit EROFS on overlayfs when the prior
# install spans image layers. Removing it first also prevents unreviewed
# files from surviving a same-version reinstall.
Expand All @@ -353,6 +362,9 @@ RUN set -eu; \
esac; \
rm -rf "$OPENCLAW_PACK_DIR"; \
fi; \
if [ "$OPENCLAW_VERSION" = "2026.6.10" ]; then \
npm ls -g --all openclaw @openclaw/fs-safe tar jszip >/dev/null; \
fi; \
if [ "$USE_REVIEWED_BASE_RUNTIME" = "1" ]; then \
echo "INFO: Reusing reviewed base mcporter $CUR_MCPORTER_VER with exact lock provenance"; \
else \
Expand Down
20 changes: 16 additions & 4 deletions Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ ARG MCPORTER_0_7_3_TARBALL=https://registry.npmjs.org/mcporter/-/mcporter-0.7.3.
COPY agents/openclaw/mcporter-runtime/package.json /usr/local/lib/nemoclaw/mcporter-runtime/package.json
COPY agents/openclaw/mcporter-runtime/package-lock.json /usr/local/lib/nemoclaw/mcporter-runtime/package-lock.json
COPY scripts/lib/reviewed-npm-archive.mts /scripts/lib/reviewed-npm-archive.mts
COPY scripts/lib/openclaw-npm-remediation.mts /scripts/lib/openclaw-npm-remediation.mts

# Keep OpenClaw's jiti-generated source cache out of /tmp so provider marker
# names do not persist in runtime snapshots or leak-scan inputs.
Expand Down Expand Up @@ -265,13 +266,21 @@ RUN --mount=type=bind,source=nemoclaw-blueprint/blueprint.yaml,target=/tmp/bluep
if [ -z "$EXPECTED_INTEGRITY" ]; then \
echo "Error: OpenClaw ${OPENCLAW_VERSION} has no committed npm integrity pin"; exit 1; \
fi; \
OPENCLAW_PACK_PATH="$(node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts \
OPENCLAW_SOURCE_PACK_PATH="$(node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts \
--package-spec "openclaw@${OPENCLAW_VERSION}" --integrity "$EXPECTED_INTEGRITY" \
--tarball-url "$EXPECTED_TARBALL" --label "OpenClaw ${OPENCLAW_VERSION}")"; \
if [ -z "$OPENCLAW_PACK_PATH" ] || [ ! -f "$OPENCLAW_PACK_PATH" ] || [ -L "$OPENCLAW_PACK_PATH" ]; then \
if [ -z "$OPENCLAW_SOURCE_PACK_PATH" ] || [ ! -f "$OPENCLAW_SOURCE_PACK_PATH" ] || [ -L "$OPENCLAW_SOURCE_PACK_PATH" ]; then \
echo "Error: reviewed OpenClaw archive path is empty or invalid"; exit 1; \
fi; \
OPENCLAW_PACK_DIR="$(dirname "$OPENCLAW_PACK_PATH")"; \
OPENCLAW_PACK_DIR="$(dirname "$OPENCLAW_SOURCE_PACK_PATH")"; \
OPENCLAW_PACK_PATH="$OPENCLAW_SOURCE_PACK_PATH"; \
OPENCLAW_RECIPE='ignore-scripts+reviewed-lifecycle-v1'; \
if [ "$OPENCLAW_VERSION" = "2026.6.10" ]; then \
OPENCLAW_PACK_PATH="$(node --experimental-strip-types /scripts/lib/openclaw-npm-remediation.mts \
--archive "$OPENCLAW_SOURCE_PACK_PATH" --package-spec "openclaw@${OPENCLAW_VERSION}" \
--working-directory "$OPENCLAW_PACK_DIR")"; \
OPENCLAW_RECIPE='ignore-scripts+reviewed-lifecycle+transitive-remediation-v1'; \
fi; \
npm install -g --ignore-scripts "$OPENCLAW_PACK_PATH" \
&& case "$OPENCLAW_VERSION" in \
2026.4.24|2026.6.10) node /usr/local/lib/node_modules/openclaw/scripts/postinstall-bundled-plugins.mjs ;; \
Expand All @@ -283,6 +292,9 @@ RUN --mount=type=bind,source=nemoclaw-blueprint/blueprint.yaml,target=/tmp/bluep
&& if [ "$OPENCLAW_INSTALLED_VERSION" != "$OPENCLAW_VERSION" ]; then \
echo "Error: Installed OpenClaw ${OPENCLAW_INSTALLED_VERSION:-unknown} does not match reviewed target ${OPENCLAW_VERSION}"; exit 1; \
fi \
&& if [ "$OPENCLAW_VERSION" = "2026.6.10" ]; then \
npm ls -g --all openclaw @openclaw/fs-safe tar jszip >/dev/null; \
fi \
&& MCPORTER_EXPECTED_INTEGRITY="" \
&& MCPORTER_EXPECTED_TARBALL="" \
&& if [ "$MCPORTER_VERSION" = "0.7.3" ]; then MCPORTER_EXPECTED_INTEGRITY="$MCPORTER_0_7_3_INTEGRITY"; MCPORTER_EXPECTED_TARBALL="$MCPORTER_0_7_3_TARBALL"; fi \
Expand Down Expand Up @@ -310,7 +322,7 @@ RUN --mount=type=bind,source=nemoclaw-blueprint/blueprint.yaml,target=/tmp/bluep
"package=openclaw@${OPENCLAW_VERSION}" \
"integrity=${EXPECTED_INTEGRITY}" \
"tarball=${EXPECTED_TARBALL}" \
'recipe=ignore-scripts+reviewed-lifecycle-v1' \
"recipe=${OPENCLAW_RECIPE}" \
"mcporter-package=mcporter@${MCPORTER_VERSION}" \
"mcporter-integrity=${MCPORTER_EXPECTED_INTEGRITY}" \
"mcporter-tarball=${MCPORTER_EXPECTED_TARBALL}" \
Expand Down
3 changes: 2 additions & 1 deletion agents/hermes/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,11 @@ COPY agents/hermes/host/managed-tool-gateway-matrix.json /opt/nemoclaw-hermes-co
COPY src/lib/tool-disclosure.ts /src/lib/tool-disclosure.ts
COPY src/lib/messaging/ /src/lib/messaging/
COPY scripts/lib/reviewed-npm-archive.mts /scripts/lib/reviewed-npm-archive.mts
COPY scripts/lib/openclaw-npm-remediation.mts /scripts/lib/openclaw-npm-remediation.mts
RUN find /opt/nemoclaw-hermes-config -type d -exec chmod 755 {} + \
&& find /opt/nemoclaw-hermes-config -type f -exec chmod 444 {} + \
&& chmod 444 /src/lib/tool-disclosure.ts \
&& chmod 444 /scripts/lib/reviewed-npm-archive.mts \
&& chmod 444 /scripts/lib/reviewed-npm-archive.mts /scripts/lib/openclaw-npm-remediation.mts \
&& chmod -R a+rX /src/lib/messaging

# Copy blueprint (shared infrastructure)
Expand Down
20 changes: 20 additions & 0 deletions ci/source-shape-test-budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,26 @@
"test": "cross-checks the allowlist against every production archive install boundary",
"category": "security"
},
{
"file": "test/openclaw-npm-remediation.test.ts",
"test": "rebuilds a guarded core archive with the patched fs-safe package bundled",
"category": "security"
},
{
"file": "test/openclaw-npm-remediation.test.ts",
"test": "rebuilds a guarded plugin archive with the patched Axios graph bundled",
"category": "security"
},
{
"file": "test/openclaw-npm-remediation.test.ts",
"test": "replaces the reviewed bundled Axios graph with the patched graph",
"category": "security"
},
{
"file": "test/openclaw-npm-remediation.test.ts",
"test": "replaces the reviewed OpenClaw core tar and brace-expansion graph",
"category": "security"
},
{
"file": "test/platform-vitest-main-workflow.test.ts",
"test": "keeps the WSL suite unprivileged with explicit root-only contracts",
Expand Down
Loading
Loading