diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e9a935198ae..e03ca25af2ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1048,7 +1048,7 @@ jobs: - name: Setup Node environment uses: ./.github/actions/setup-node-env with: - node-version: "22.18.0" + node-version: "22.19.0" cache-key-suffix: "node22-pnpm11" install-bun: "false" diff --git a/.github/workflows/docs-sync-publish.yml b/.github/workflows/docs-sync-publish.yml index 51ac3457be7a..8ed7e80382cd 100644 --- a/.github/workflows/docs-sync-publish.yml +++ b/.github/workflows/docs-sync-publish.yml @@ -43,7 +43,7 @@ jobs: if: env.OPENCLAW_DOCS_SYNC_TOKEN != '' uses: actions/setup-node@v6 with: - node-version: "22.18.0" + node-version: "24.x" - name: Clone publish repo if: env.OPENCLAW_DOCS_SYNC_TOKEN != '' diff --git a/AGENTS.md b/AGENTS.md index 9b22be90f437..42cd65ed6073 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -50,7 +50,7 @@ Skills own workflows; root owns hard policy and routing. ## Commands -- Runtime: Node 22+. Keep Node + Bun paths working. +- Runtime: Node 22.19+; Node 24 recommended. Keep Node + Bun paths working. - Package manager/runtime: repo defaults only. No swaps without approval. - Install: `pnpm install` (keep Bun lock/patches aligned if touched). - Sharp/Homebrew libvips source-build fail: `SHARP_IGNORE_GLOBAL_LIBVIPS=1 pnpm install`. diff --git a/SECURITY.md b/SECURITY.md index bbdb77819018..59fce1efaf30 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -312,7 +312,7 @@ OpenClaw's web interface (Gateway Control UI + HTTP endpoints) is intended for * ### Node.js Version -OpenClaw requires **Node.js 22.16.0 or later** (LTS). This version includes important security patches: +OpenClaw requires **Node.js 22.19.0 or later** (LTS). Node 24 is the recommended default runtime for new installs. The minimum version includes important security patches: - CVE-2025-59466: async_hooks DoS vulnerability - CVE-2026-21636: Permission model bypass vulnerability @@ -320,7 +320,7 @@ OpenClaw requires **Node.js 22.16.0 or later** (LTS). This version includes impo Verify your Node.js version: ```bash -node --version # Should be v22.16.0 or later +node --version # Should be v22.19.0 or later ``` ### Docker Security diff --git a/apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift b/apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift index 3fbf2201247f..cf0e6d9a8919 100644 --- a/apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift +++ b/apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift @@ -679,7 +679,7 @@ extension OnboardingView { } else if !self.cliInstalled, self.cliInstallLocation == nil { Text( """ - Installs a user-space Node 22+ runtime and the CLI (no Homebrew). + Installs a user-space Node 22.19+ runtime and the CLI (no Homebrew). Rerun anytime to reinstall or update. """) .font(.footnote) diff --git a/docs/plugins/building-plugins.md b/docs/plugins/building-plugins.md index e0d6298e2842..7da952fb752a 100644 --- a/docs/plugins/building-plugins.md +++ b/docs/plugins/building-plugins.md @@ -25,7 +25,7 @@ Bare package specs still install from npm during the launch cutover. Use the ## Requirements -- Use Node 22 or newer and a package manager such as `npm` or `pnpm`. +- Use Node 22.19 or newer and a package manager such as `npm` or `pnpm`. - Be familiar with TypeScript ESM modules. - For in-repo bundled plugin work, clone the repository and run `pnpm install`. Source-checkout plugin development is pnpm-only because OpenClaw loads bundled diff --git a/src/cli/daemon-cli/install.test.ts b/src/cli/daemon-cli/install.test.ts index 7dcf65eebc08..817f145b0b8c 100644 --- a/src/cli/daemon-cli/install.test.ts +++ b/src/cli/daemon-cli/install.test.ts @@ -667,7 +667,7 @@ describe("runDaemonInstall", () => { NODE_USE_SYSTEM_CA: undefined, })); service.readCommand.mockResolvedValue({ - programArguments: ["/home/test/.nvm/versions/node/v22.18.0/bin/node", "dist/entry.js"], + programArguments: ["/home/test/.nvm/versions/node/v22.19.0/bin/node", "dist/entry.js"], environment: {}, } as never); @@ -675,7 +675,7 @@ describe("runDaemonInstall", () => { expect(installDaemonServiceAndEmitMock).toHaveBeenCalledTimes(1); expectFields(readFirstNodeStartupTlsEnvironmentArg(), { - execPath: "/home/test/.nvm/versions/node/v22.18.0/bin/node", + execPath: "/home/test/.nvm/versions/node/v22.19.0/bin/node", }); }); diff --git a/src/infra/stable-node-path.test.ts b/src/infra/stable-node-path.test.ts index af9bd0372de4..fb4597ea4e8e 100644 --- a/src/infra/stable-node-path.test.ts +++ b/src/infra/stable-node-path.test.ts @@ -12,7 +12,7 @@ describe("resolveStableNodePath", () => { it("prefers the Homebrew opt symlink for default and versioned formulas", async () => { await withTempDir({ prefix: "openclaw-stable-node-" }, async (prefix) => { const defaultNode = path.join(prefix, "Cellar", "node", "25.7.0", "bin", "node"); - const versionedNode = path.join(prefix, "Cellar", "node@22", "22.17.0", "bin", "node"); + const versionedNode = path.join(prefix, "Cellar", "node@22", "22.19.0", "bin", "node"); const optDefault = path.join(prefix, "opt", "node", "bin", "node"); const optVersioned = path.join(prefix, "opt", "node@22", "bin", "node"); @@ -29,7 +29,7 @@ describe("resolveStableNodePath", () => { it("falls back to the bin symlink for the default formula, otherwise original path", async () => { await withTempDir({ prefix: "openclaw-stable-node-" }, async (prefix) => { const defaultNode = path.join(prefix, "Cellar", "node", "25.7.0", "bin", "node"); - const versionedNode = path.join(prefix, "Cellar", "node@22", "22.17.0", "bin", "node"); + const versionedNode = path.join(prefix, "Cellar", "node@22", "22.19.0", "bin", "node"); const binNode = path.join(prefix, "bin", "node"); await fs.mkdir(path.dirname(binNode), { recursive: true });