Node install: persist gateway token in service env (#31122)

* Node daemon: persist gateway token env

* changelog: add credits for node gateway token fix

* changelog: credit byungsker for node token service fix

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
Mark L
2026-03-02 09:35:24 +08:00
committed by GitHub
parent ca770622b3
commit f1354869bd
3 changed files with 40 additions and 0 deletions

View File

@@ -108,6 +108,7 @@ Docs: https://docs.openclaw.ai
- Gateway/Control UI origins: support wildcard `"*"` in `gateway.controlUi.allowedOrigins` for trusted remote access setups. Landed from contributor PR #31088 by @frankekn. Thanks @frankekn.
- Cron/Isolated CLI timeout ratio: avoid reusing persisted CLI session IDs on fresh isolated cron runs so the fresh watchdog profile is used and jobs do not abort at roughly one-third of configured `timeoutSeconds`. (#30140) Thanks @ningding97.
- Security/Sandbox media reads: eliminate sandbox media TOCTOU symlink-retarget escapes by enforcing root-scoped boundary-safe reads at attachment/image load time and consolidating shared safe-read helpers across sandbox media callsites. This ships in the next npm release. Thanks @tdjackey for reporting.
- Node host/service auth env: include `OPENCLAW_GATEWAY_TOKEN` in `openclaw node install` service environments (with `CLAWDBOT_GATEWAY_TOKEN` compatibility fallback) so installed node services keep remote gateway token auth across restart/reboot. Fixes #31041. Thanks @OneStepAt4time for reporting, @byungsker, @liuxiaopai-ai, and @vincentkoc.
- Security/Subagents sandbox inheritance: block sandboxed sessions from spawning cross-agent subagents that would run unsandboxed, preventing runtime sandbox downgrade via `sessions_spawn agentId`. Thanks @tdjackey for reporting.
- Security/Workspace safe writes: harden `writeFileWithinRoot` against symlink-retarget TOCTOU races by opening existing files without truncation, creating missing files with exclusive create, deferring truncation until post-open identity+boundary validation, and removing out-of-root create artifacts on blocked races; added regression tests for truncate/create race paths. This ships in the next npm release (`2026.3.1`). Thanks @tdjackey for reporting.
- Security/Node metadata policy: harden node platform classification against Unicode confusables and switch unknown platform defaults to a conservative allowlist that excludes `system.run`/`system.which` unless explicitly allowlisted, preventing metadata canonicalization drift from broadening node command permissions. Thanks @tdjackey for reporting.

View File

@@ -364,6 +364,42 @@ describe("buildNodeServiceEnvironment", () => {
expect(env.HOME).toBe("/home/user");
});
it("passes through OPENCLAW_GATEWAY_TOKEN for node services", () => {
const env = buildNodeServiceEnvironment({
env: { HOME: "/home/user", OPENCLAW_GATEWAY_TOKEN: " node-token " },
});
expect(env.OPENCLAW_GATEWAY_TOKEN).toBe("node-token");
});
it("maps legacy CLAWDBOT_GATEWAY_TOKEN to OPENCLAW_GATEWAY_TOKEN for node services", () => {
const env = buildNodeServiceEnvironment({
env: { HOME: "/home/user", CLAWDBOT_GATEWAY_TOKEN: " legacy-token " },
});
expect(env.OPENCLAW_GATEWAY_TOKEN).toBe("legacy-token");
});
it("prefers OPENCLAW_GATEWAY_TOKEN over legacy CLAWDBOT_GATEWAY_TOKEN", () => {
const env = buildNodeServiceEnvironment({
env: {
HOME: "/home/user",
OPENCLAW_GATEWAY_TOKEN: "openclaw-token",
CLAWDBOT_GATEWAY_TOKEN: "legacy-token",
},
});
expect(env.OPENCLAW_GATEWAY_TOKEN).toBe("openclaw-token");
});
it("omits OPENCLAW_GATEWAY_TOKEN when both token env vars are empty", () => {
const env = buildNodeServiceEnvironment({
env: {
HOME: "/home/user",
OPENCLAW_GATEWAY_TOKEN: " ",
CLAWDBOT_GATEWAY_TOKEN: " ",
},
});
expect(env.OPENCLAW_GATEWAY_TOKEN).toBeUndefined();
});
it("forwards proxy environment variables for node services", () => {
const env = buildNodeServiceEnvironment({
env: {

View File

@@ -279,6 +279,8 @@ export function buildNodeServiceEnvironment(params: {
}): Record<string, string | undefined> {
const { env } = params;
const platform = params.platform ?? process.platform;
const gatewayToken =
env.OPENCLAW_GATEWAY_TOKEN?.trim() || env.CLAWDBOT_GATEWAY_TOKEN?.trim() || undefined;
const stateDir = env.OPENCLAW_STATE_DIR;
const configPath = env.OPENCLAW_CONFIG_PATH;
const tmpDir = env.TMPDIR?.trim() || os.tmpdir();
@@ -296,6 +298,7 @@ export function buildNodeServiceEnvironment(params: {
NODE_EXTRA_CA_CERTS: nodeCaCerts,
OPENCLAW_STATE_DIR: stateDir,
OPENCLAW_CONFIG_PATH: configPath,
OPENCLAW_GATEWAY_TOKEN: gatewayToken,
OPENCLAW_LAUNCHD_LABEL: resolveNodeLaunchAgentLabel(),
OPENCLAW_SYSTEMD_UNIT: resolveNodeSystemdServiceName(),
OPENCLAW_WINDOWS_TASK_NAME: resolveNodeWindowsTaskName(),