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
2 changes: 1 addition & 1 deletion .github/actions/ci-reviewed-npm-audit/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ runs:
- name: Setup production-compatible Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22.23.1"
node-version: "22.23.2"

- name: Download and verify production npm
shell: bash
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/candidate-compatibility.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ jobs:
continue-on-error: true
working-directory: candidate-source
env:
DOCKER_GRPC_PROBE_IMAGE: node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba
DOCKER_GRPC_PROBE_IMAGE: node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c
E2E_ARTIFACT_DIR: ${{ github.workspace }}/candidate-source/e2e-artifacts/live/openshell-gateway-auth-contract
E2E_JOB: "1"
E2E_TARGET_ID: openshell-gateway-auth-contract
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,7 @@ jobs:
NEMOCLAW_RUN_LIVE_E2E: "1"
NEMOCLAW_NON_INTERACTIVE: "1"
NEMOCLAW_OPENSHELL_PIN_VERSION: "0.0.101"
DOCKER_GRPC_PROBE_IMAGE: "node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba"
DOCKER_GRPC_PROBE_IMAGE: "node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand Down Expand Up @@ -6233,7 +6233,7 @@ jobs:
shell: bash
run: |
set -euo pipefail
docker pull node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba
docker pull node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c

- name: Remove Docker auth before release-pinned fixture
if: always()
Expand Down
10 changes: 5 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
ARG CODEX_ACP_LINUX_ARM64_0_11_1_INTEGRITY=sha512-I1f6WoSLbLlsWq4zH+vtwdoc4Y41mqRXPpSkfgIifxBw34QmWJmi37etZ7lKTYp6R+J/Z4PUN0rsmnsmKpBZTw==

# Stage 1: Build TypeScript plugin from source
FROM node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba AS builder
FROM node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c AS builder
ENV NPM_CONFIG_AUDIT=false \
NPM_CONFIG_FUND=false \
NPM_CONFIG_UPDATE_NOTIFIER=false \
Expand Down Expand Up @@ -139,7 +139,7 @@

# Reviewed-archive invariants (#5896): checksum-addressed source archives,
# committed SRI verification, offline installation, and exact architecture.
FROM node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba AS codex-acp-runtime
FROM node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c AS codex-acp-runtime
ARG TARGETARCH
ARG CODEX_ACP_0_11_1_INTEGRITY
ARG CODEX_ACP_LINUX_AMD64_0_11_1_INTEGRITY
Expand All @@ -162,7 +162,7 @@
rm -rf /tmp/codex-acp; \
command -v codex-acp >/dev/null

FROM node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba AS wechat-npm-cache
FROM node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c AS wechat-npm-cache
COPY agents/openclaw/wechat-runtime/package.json agents/openclaw/wechat-runtime/package-lock.json /opt/wechat-runtime/
COPY scripts/checks/materialize-locked-npm-cache-seed.mts /opt/checks/
COPY scripts/lib/reviewed-npm-archive.mts scripts/lib/seed-reviewed-npm-cache.mts /opt/nemoclaw-build-tools/
Expand Down Expand Up @@ -476,10 +476,10 @@

# Keep the complete managed-image messaging dependency graph inert for normal
# Dockerfile builds. Release-image builds select the exact-lock cache stage.
FROM node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba AS openclaw-managed-messaging-npm-cache-0
FROM node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c AS openclaw-managed-messaging-npm-cache-0
RUN install -d -o root -g root -m 0755 /out/npm-cache

FROM node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba AS openclaw-managed-messaging-npm-cache-1
FROM node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c AS openclaw-managed-messaging-npm-cache-1
ARG TARGETARCH
ENV NPM_CONFIG_AUDIT=false \
NPM_CONFIG_FUND=false \
Expand Down Expand Up @@ -1643,10 +1643,10 @@
# CHAT_UI_URL is a non-loopback address (Brev Launchable, remote deployments)
# since terminal-based pairing is impossible in those contexts.
# Default: "0" (device auth enabled for local deployments — secure by default).
ARG NEMOCLAW_DISABLE_DEVICE_AUTH=0

Check warning on line 1646 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NEMOCLAW_DISABLE_DEVICE_AUTH") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 1646 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NEMOCLAW_DISABLE_DEVICE_AUTH") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
# Internal audit provenance for the opt-out above. Standard onboarding rewrites
# this to managed-onboard; direct image builders retain operator provenance.
ARG NEMOCLAW_DEVICE_AUTH_OPT_OUT_SOURCE=operator

Check warning on line 1649 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NEMOCLAW_DEVICE_AUTH_OPT_OUT_SOURCE") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 1649 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NEMOCLAW_DEVICE_AUTH_OPT_OUT_SOURCE") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
# Compatibility build arg for older custom Dockerfiles and rebuild tooling.
# NemoClaw-managed images intentionally do not consume it; gateway auth tokens
# are generated at container startup and are never baked into image layers.
Expand Down Expand Up @@ -1680,7 +1680,7 @@
# NEMOCLAW_MESSAGING_PLAN_B64 intentionally remains ARG-only: Docker exposes it
# to build RUN processes without retaining the full plan in the final image env.
# Direct ARG interpolation into inline source is a code injection vector (C-2).
ENV NEMOCLAW_MODEL=${NEMOCLAW_MODEL} \

Check warning on line 1683 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "NEMOCLAW_DEVICE_AUTH_OPT_OUT_SOURCE") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 1683 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "NEMOCLAW_DISABLE_DEVICE_AUTH") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 1683 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "NEMOCLAW_DEVICE_AUTH_OPT_OUT_SOURCE") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 1683 in Dockerfile

View workflow job for this annotation

GitHub Actions / PR build and direct managed startup (OpenClaw)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "NEMOCLAW_DISABLE_DEVICE_AUTH") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
NEMOCLAW_INFERENCE_PROVIDER_ID=${NEMOCLAW_INFERENCE_PROVIDER_ID} \
NEMOCLAW_UPSTREAM_PROVIDER=${NEMOCLAW_UPSTREAM_PROVIDER} \
NEMOCLAW_PRIMARY_MODEL_REF=${NEMOCLAW_PRIMARY_MODEL_REF} \
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ ARG PERL_PACKAGE_REVISION=1nemoclaw1
# Debian trixie has not published libssh2 or Python packages containing the
# reviewed upstream fixes. Build native packages once and install the same
# artifacts into the managed OpenClaw image.
FROM node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba AS native-security-builder
FROM node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c AS native-security-builder

RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential=12.12 \
Expand Down Expand Up @@ -96,7 +96,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN bash /scripts/security/build-perl-security-packages.sh \
/out "${PERL_VERSION}" "${PERL_SHA256}" "${PERL_PACKAGE_REVISION}"

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

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

Expand Down
4 changes: 2 additions & 2 deletions agents/langchain-deepagents-code/Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ARG PERL_PACKAGE_REVISION=1nemoclaw1

ARG NEMOCLAW_CORPORATE_CA_B64=

FROM node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba AS native-security-builder
FROM node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c AS native-security-builder

ARG NEMOCLAW_CORPORATE_CA_B64

Expand Down Expand Up @@ -61,7 +61,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN bash /scripts/security/build-perl-security-packages.sh \
/out "${PERL_VERSION}" "${PERL_SHA256}" "${PERL_PACKAGE_REVISION}"

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

ARG NEMOCLAW_CORPORATE_CA_B64

Expand Down
2 changes: 1 addition & 1 deletion ci/reviewed-npm-audit.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"schemaVersion": 2,
"nodeVersion": "22.23.1",
"nodeVersion": "22.23.2",
"registryOrigin": "https://registry.npmjs.org/",
"severityThreshold": "high",
"exceptionFile": "ci/npm-audit-exceptions.json",
Expand Down
5 changes: 5 additions & 0 deletions ci/source-shape-test-budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,11 @@
"test": "replaces the reviewed OpenClaw core tar and brace-expansion graph",
"category": "security"
},
{
"file": "test/node-tar-dockerfile-contract.test.ts",
"test": "rejects an isolated unreviewed Deep Agents Code Node base pin",
"category": "security"
},
{
"file": "test/openclaw-dependency-review.test.ts",
"test": "copies the legacy OpenClaw remediation helper before the base build invokes it",
Expand Down
2 changes: 1 addition & 1 deletion scripts/patch-bundled-npm-tar.mts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const MINIMUM_SAFE_TAR_VERSION = "7.5.19";
* The Dockerfile contract test forces that review whenever either pin changes.
*/
export const NODE_BASES_REQUIRING_BUNDLED_NPM_TAR_PATCH = [
"node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba",
"node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c",
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"node:24-trixie-slim@sha256:05c08ce4291e9a58f59456a7985176defb12cdd42271f35ff81a3e167ea61d4c",
] as const;

Expand Down
2 changes: 1 addition & 1 deletion test/e2e/live/openclaw-plugin-runtime-exdev.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const NEMOCLAW_SOURCE_REPOSITORY = "https://github.com/NVIDIA/NemoClaw.git";
const RELEASE_BUILDER_IMAGE_REF =
"node:22-trixie-slim@sha256:2d9f5c76c8f4dd36e8f253bee5d828a83a6c09f36188f0b0414325232e0b175d";
const CURRENT_BUILDER_IMAGE_REF =
"node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba";
"node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c";
const TOOL_DISCLOSURE_ENV_REFERENCE = "${NEMOCLAW_TOOL_DISCLOSURE}";
const SANDBOX_NAME = process.env.NEMOCLAW_SANDBOX_NAME ?? "e2e-oc-exdev";
const ONBOARD_TIMEOUT_MS = 25 * 60_000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import type { TestProgress } from "../fixtures/progress.ts";

const SANDBOX_JWT_SUBJECT_PREFIX = "spiffe://openshell/sandbox/";
const DOCKER_GRPC_PROBE_IMAGE =
"node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba";
"node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c";

type SkipFn = (message?: string) => void;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ describe("OpenClaw plugin runtime EXDEV workflow boundary", () => {
"openclaw-plugin-runtime-exdev action 'actions/checkout@v6' must pin a full SHA",
"openclaw-plugin-runtime-exdev checkout must disable persisted credentials",
"openclaw-plugin-runtime-exdev must use the reviewed prepare-e2e action",
"openclaw-plugin-runtime-exdev step 'Pre-pull release-matched Docker Hub builder image' must run: docker pull node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba",
"openclaw-plugin-runtime-exdev step 'Pre-pull release-matched Docker Hub builder image' must run: docker pull node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c",
"openclaw-plugin-runtime-exdev must always revoke Docker auth before the release-pinned fixture",
"openclaw-plugin-runtime-exdev must use the pinned Docker auth cleanup action before artifact restore",
"openclaw-plugin-runtime-exdev runtime proof must not receive workflow credentials",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe("OpenShell gateway auth contract workflow boundary", () => {
"openshell-gateway-auth-contract must run on main pushes and retain manual selectors",
"openshell-gateway-auth-contract must run on ubuntu-latest",
"openshell-gateway-auth-contract must retain its 20 minute resource budget",
"openshell-gateway-auth-contract must set DOCKER_GRPC_PROBE_IMAGE=node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba",
"openshell-gateway-auth-contract must set DOCKER_GRPC_PROBE_IMAGE=node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c",
"openshell-gateway-auth-contract must set E2E_ARTIFACT_DIR=${{ github.workspace }}/e2e-artifacts/live/openshell-gateway-auth-contract",
"openshell-gateway-auth-contract must set NEMOCLAW_OPENSHELL_PIN_VERSION to an exact version",
"openshell-gateway-auth-contract must not expose NVIDIA_API_KEY at job scope",
Expand Down
53 changes: 47 additions & 6 deletions test/node-tar-dockerfile-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,29 @@ const dockerfiles = [
] as const;
const patchCommand = "node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts";
const npmRootArguments = ["--npm-root", "/usr/local/lib/node_modules/npm"] as const;
const pinnedBaseDockerfiles = [
"Dockerfile.base",
"agents/hermes/Dockerfile.base",
"agents/langchain-deepagents-code/Dockerfile.base",
] as const;
const reviewedNodeBases = new Set<string>(NODE_BASES_REQUIRING_BUNDLED_NPM_TAR_PATCH);

function nodeBaseReferences(source: string): string[] {
return [
...new Set(
[...source.matchAll(/^FROM\s+(node:[^\s]+@sha256:[0-9a-f]{64})(?:\s|$)/gmu)].map(
(match) => match[1]!,
),
),
].sort();
}

function assertReviewedNodeBases(file: string, source: string): void {
const bases = nodeBaseReferences(source);
assert(bases.length > 0, `${file} must pin at least one upstream Node base image`);
const unreviewed = bases.filter((base) => !reviewedNodeBases.has(base));
assert.deepEqual(unreviewed, [], `${file} contains an unreviewed upstream Node base image`);
}

function completedStage(source: string): string {
const finalStageStart = [...source.matchAll(/^FROM\b/gmu)].at(-1)?.index;
Expand All @@ -48,13 +71,31 @@ function namedStage(source: string, name: string): string {

describe("node-tar image remediation contract", () => {
it("binds the remediation lifecycle to the affected upstream Node image pins", () => {
const pinnedBaseSources = ["Dockerfile.base", "agents/hermes/Dockerfile.base"]
.map((file) => fs.readFileSync(path.join(repoRoot, file), "utf8"))
.join("\n");

for (const base of NODE_BASES_REQUIRING_BUNDLED_NPM_TAR_PATCH) {
expect(pinnedBaseSources, base).toContain(`FROM ${base}`);
const observedBases = new Set<string>();
for (const file of pinnedBaseDockerfiles) {
const source = fs.readFileSync(path.join(repoRoot, file), "utf8");
assertReviewedNodeBases(file, source);
for (const base of nodeBaseReferences(source)) observedBases.add(base);
}
expect([...observedBases].sort()).toEqual(
[...NODE_BASES_REQUIRING_BUNDLED_NPM_TAR_PATCH].sort(),
);
});

// source-shape-contract: security -- Each managed Dockerfile must remain bound to a reviewed Node base digest.
it("rejects an isolated unreviewed Deep Agents Code Node base pin", () => {
const file = "agents/langchain-deepagents-code/Dockerfile.base";
const source = fs.readFileSync(path.join(repoRoot, file), "utf8");
const reviewedBase = NODE_BASES_REQUIRING_BUNDLED_NPM_TAR_PATCH.find((base) =>
base.startsWith("node:22-"),
);
assert(reviewedBase !== undefined, "the reviewed Node 22 base must be registered");
const unreviewedBase = `node:22-trixie-slim@sha256:${"0".repeat(64)}`;
const changedSource = source.replaceAll(reviewedBase, unreviewedBase);

expect(() => assertReviewedNodeBases(file, changedSource)).toThrow(
`${file} contains an unreviewed upstream Node base image`,
);
});

it.each([
Expand Down
6 changes: 3 additions & 3 deletions test/openclaw-real-patched-dist-harness.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ function resolveRealOpenClawNodeRuntime(
supportedNode22 ||
runtimeMismatch(
version,
"Node >=22.22.3 <23 (the Dockerfile runtime is Node 22.23.1)",
"Node >=22.22.3 <23 (the Dockerfile runtime is Node 22.23.2)",
REAL_OPENCLAW_NODE_ENV,
);

Expand Down Expand Up @@ -317,11 +317,11 @@ describe("OpenClaw real patched-dist materialization guard", () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-openclaw-node-runtime-"));
try {
const fakeNode = path.join(tmp, "node");
fs.writeFileSync(fakeNode, "#!/bin/sh\nprintf 'v22.23.1\\n'\n", { mode: 0o700 });
fs.writeFileSync(fakeNode, "#!/bin/sh\nprintf 'v22.23.2\\n'\n", { mode: 0o700 });

expect(resolveRealOpenClawNodeRuntime({ [REAL_OPENCLAW_NODE_ENV]: fakeNode })).toEqual({
executable: fakeNode,
version: "v22.23.1",
version: "v22.23.2",
});
} finally {
fs.rmSync(tmp, { recursive: true, force: true });
Expand Down
6 changes: 3 additions & 3 deletions test/platform-vitest-main-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ describe("platform Vitest main workflow", () => {
for (const installStep of installSteps) {
expect(installStep, "missing WSL Node.js install step").toBeDefined();
const run = installStep?.run ?? "";
expect(run).toContain('node_version="22.23.1"');
expect(run).toContain('node_version="22.23.2"');
expect(run).toMatch(
/x86_64\)[\s\S]*?node_arch="x64"[\s\S]*?node_sha256="9749e988f437343b7fa832c69ded82a312e41a03116d766797ac14f6f9eee578"[\s\S]*?;;/u,
/x86_64\)[\s\S]*?node_arch="x64"[\s\S]*?node_sha256="d60acfe00a2932254bb0ad20e01b0d74397a0875595de719654b214f4b03f307"[\s\S]*?;;/u,
);
expect(run).toMatch(
/aarch64 \| arm64\)[\s\S]*?node_arch="arm64"[\s\S]*?node_sha256="0294e8b915ab75f92c7513d2fcb830ae06e10684e6c603e99a87dbf8835389c1"[\s\S]*?;;/u,
/aarch64 \| arm64\)[\s\S]*?node_arch="arm64"[\s\S]*?node_sha256="fff4078c5def658577f92c88db7db3bc0072924bfb93fe52c1e744a54e94abb8"[\s\S]*?;;/u,
);
expect(run).toContain(
'node_url="https://nodejs.org/dist/v${node_version}/node-v${node_version}-linux-${node_arch}.tar.xz"',
Expand Down
2 changes: 1 addition & 1 deletion test/reviewed-npm-audit-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ describe("trusted reviewed npm audit workflow (#5896)", () => {
replacementLockSha256: digest,
},
],
nodeVersion: "22.23.1",
nodeVersion: "22.23.2",
registryOrigin: "https://registry.npmjs.org/",
schemaVersion: 2,
severityThreshold: "high",
Expand Down
2 changes: 1 addition & 1 deletion tools/e2e/cli-artifact-workflow-boundary.mts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const CLI_ARTIFACT_PROVENANCE_STEP = "Record CLI artifact provenance";
const CANDIDATE_CHECKOUT_STEP_CONTENT_SHA256 =
"3578a053cede863f7aa4814d8399b4ca21ea0b77cee712e6d549c684818f11dd";
const CLI_ARTIFACT_WORKFLOW_CONTRACT_SHA256 =
"715e590815e3b0e3e1511d19dc548c0a08c28d3cb9255e872c438eeed9028a7f";
"c48ec7ff7a2cfc9c111f0f878799f89976bb9475a9a96725e07d90654770e763";

type WorkflowRecord = Record<string, unknown>;
type WorkflowStep = WorkflowRecord & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const JOB_CONTRACTS = [
runName: "Run OpenClaw custom-plugin lifecycle and runtime-deps EXDEV live test",
uploadName: "Upload OpenClaw plugin runtime-deps EXDEV artifacts",
builderImage:
"node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba",
"node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c",
},
] as const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const FULL_SHA_ACTION = /^[^\s@]+@[0-9a-f]{40}$/u;
const MAIN_AND_MANUAL_CONDITION =
"${{ (github.event_name != 'workflow_dispatch' || (inputs.jobs == '' && inputs.targets == '')) || contains(format(',{0},', inputs.jobs), ',openshell-gateway-auth-contract,') || contains(format(',{0},', inputs.targets), ',openshell-gateway-auth-contract,') }}";
const GATEWAY_PROBE_IMAGE =
"node:22-trixie-slim@sha256:e6d9a389d34ff9678438af985c9913fbd1eb6ed36e80fea56644f4b4f6dd70ba";
"node:22-trixie-slim@sha256:db8a96a63e5264607ada2d206758876ebbed6a12be2ada7517793cbfb0c2a29c";
const ARTIFACT_SAFETY_GATED_UPLOAD =
"${{ always() && steps.artifact_safety.outcome == 'success' && steps.artifact_safety.outputs.approved_path != '' }}";
const APPROVED_ARTIFACT_PATH = "${{ steps.artifact_safety.outputs.approved_path }}";
Expand Down
6 changes: 3 additions & 3 deletions tools/wsl/ci-helper.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -302,15 +302,15 @@ function Install-WslUbuntuDependencies {
function Get-WslNodeInstallScript {
return @'
set -euo pipefail
node_version="22.23.1"
node_version="22.23.2"
case "$(uname -m)" in
x86_64)
node_arch="x64"
node_sha256="9749e988f437343b7fa832c69ded82a312e41a03116d766797ac14f6f9eee578"
node_sha256="d60acfe00a2932254bb0ad20e01b0d74397a0875595de719654b214f4b03f307"
;;
aarch64 | arm64)
node_arch="arm64"
node_sha256="0294e8b915ab75f92c7513d2fcb830ae06e10684e6c603e99a87dbf8835389c1"
node_sha256="fff4078c5def658577f92c88db7db3bc0072924bfb93fe52c1e744a54e94abb8"
;;
*)
echo "Unsupported Node.js architecture: $(uname -m)" >&2
Expand Down
Loading