From eec3182cbbc3cf20baae8e2f90112b178ad4bcdf Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 22 Feb 2026 13:19:12 +0100 Subject: [PATCH] fix(utils): guard resolveUserPath for missing workspace input --- CHANGELOG.md | 1 + src/utils.test.ts | 5 +++++ src/utils.ts | 3 +++ 3 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00d6a23f24d..eb611d63dcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Agents/Workspace: guard `resolveUserPath` against undefined/null input to prevent `Cannot read properties of undefined (reading 'trim')` crashes when workspace paths are missing in embedded runner flows. - Auth/Profiles: keep active `cooldownUntil`/`disabledUntil` windows immutable across retries so mid-window failures cannot extend recovery indefinitely; only recompute a backoff window after the previous deadline has expired. This resolves cron/inbound retry loops that could trap gateways until manual `usageStats` cleanup. (#23516, #23536) Thanks @arosstale. - Channels/Security: fail closed on missing provider group policy config by defaulting runtime group policy to `allowlist` (instead of inheriting `channels.defaults.groupPolicy`) when `channels.` is absent across message channels, and align runtime + security warnings/docs to the same fallback behavior (Slack, Discord, iMessage, Telegram, WhatsApp, Signal, LINE, Matrix, Mattermost, Google Chat, IRC, Nextcloud Talk, Feishu, and Zalo user flows; plus Discord message/native-command paths). (#23367) Thanks @bmendonca3. - Gateway/Onboarding: harden remote gateway onboarding defaults and guidance by defaulting discovered direct URLs to `wss://`, rejecting insecure non-loopback `ws://` targets in onboarding validation, and expanding remote-security remediation messaging across gateway client/call/doctor flows. (#23476) Thanks @bmendonca3. diff --git a/src/utils.test.ts b/src/utils.test.ts index 14284b75470..ec9a0f4a1a1 100644 --- a/src/utils.test.ts +++ b/src/utils.test.ts @@ -240,4 +240,9 @@ describe("resolveUserPath", () => { expect(resolveUserPath("")).toBe(""); expect(resolveUserPath(" ")).toBe(""); }); + + it("returns empty string for undefined/null input", () => { + expect(resolveUserPath(undefined as unknown as string)).toBe(""); + expect(resolveUserPath(null as unknown as string)).toBe(""); + }); }); diff --git a/src/utils.ts b/src/utils.ts index 49e14e0d048..55efabb1ba2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -283,6 +283,9 @@ export function truncateUtf16Safe(input: string, maxLen: number): string { } export function resolveUserPath(input: string): string { + if (!input) { + return ""; + } const trimmed = input.trim(); if (!trimmed) { return trimmed;