Security
- Gateway/WebSocket: enforce browser origin validation for all browser-originated connections regardless of whether proxy headers are present, closing a cross-site WebSocket hijacking path in
trusted-proxymode that could grant untrusted originsoperator.adminaccess. (GHSA-5wcw-8jjv-m286)
Changes
- OpenRouter/models: add temporary Hunter Alpha and Healer Alpha entries to the built-in catalog so OpenRouter users can try the new free stealth models during their roughly one-week availability window. (#43642) Thanks @ping-Toven.
- iOS/Home canvas: add a bundled welcome screen with a live agent overview that refreshes on connect, reconnect, and foreground return, and move the compact connection pill off the top-left canvas overlay. (#42456) Thanks @ngutman.
- iOS/Home canvas: replace floating controls with a docked toolbar, make the bundled home scaffold adapt to smaller phones, and open chat in the resolved main session instead of a synthetic
iossession. (#42456) Thanks @ngutman. - macOS/chat UI: add a chat model picker, persist explicit thinking-level selections across relaunch, and harden provider-aware session model sync for the shared chat composer. (#42314) Thanks @ImLukeF.
- Onboarding/Ollama: add first-class Ollama setup with Local or Cloud + Local modes, browser-based cloud sign-in, curated model suggestions, and cloud-model handling that skips unnecessary local pulls. (#41529) Thanks @BruceMacD.
- OpenCode/onboarding: add new OpenCode Go provider, treat Zen and Go as one OpenCode setup in the wizard/docs while keeping the runtime providers split, store one shared OpenCode key for both profiles, and stop overriding the built-in
opencode-gocatalog routing. (#42313) Thanks @ImLukeF and @vincentkoc. - Memory: add opt-in multimodal image and audio indexing for
memorySearch.extraPathswith Geminigemini-embedding-2-preview, strict fallback gating, and scope-based reindexing. (#43460) Thanks @gumadeiras. - Memory/Gemini: add
gemini-embedding-2-previewmemory-search support with configurable output dimensions and automatic reindexing when the configured dimensions change. (#42501) Thanks @BillChirico and @gumadeiras. - macOS/onboarding: detect when remote gateways need a shared auth token, explain where to find it on the gateway host, and clarify when a successful check used paired-device auth instead. (#43100) Thanks @ngutman.
- Discord/auto threads: add
autoArchiveDurationchannel config for auto-created threads so Discord thread archiving can stay at 1 hour, 1 day, 3 days, or 1 week instead of always using the 1-hour default. (#35065) Thanks @davidguttman. - iOS/TestFlight: add a local beta release flow with Fastlane prepare/archive/upload support, canonical beta bundle IDs, and watch-app archive fixes. (#42991) Thanks @ngutman.
- ACP/sessions_spawn: add optional
resumeSessionIdforruntime: "acp"so spawned ACP sessions can resume an existing ACPX/Codex conversation instead of always starting fresh. (#41847) Thanks @pejmanjohn. - Gateway/node pending work: add narrow in-memory pending-work queue primitives (
node.pending.enqueue/node.pending.drain) and wake-helper reuse as a foundation for dormant-node work delivery. (#41409) Thanks @mbelinky. - Git/runtime state: ignore the gateway-generated
.dev-statefile so local runtime state does not show up as untracked repo noise. (#41848) Thanks @smysle. - Exec/child commands: mark child command environments with
OPENCLAW_CLIso subprocesses can detect when they were launched from the OpenClaw CLI. (#41411) Thanks @vincentkoc.
Breaking
- Cron/doctor: tighten isolated cron delivery so cron jobs can no longer notify through ad hoc agent sends or fallback main-session summaries, and add
openclaw doctor --fixmigration for legacy cron storage and legacy notify/webhook delivery metadata. (#40998) Thanks @mbelinky.
Fixes
- Agents/text sanitization: strip leaked model control tokens (
<|...|>and full-width<|...|>variants) from user-facing assistant text, preventing GLM-5 and DeepSeek internal delimiters from reaching end users. (#42173) Thanks @imwyvern. - iOS/gateway foreground recovery: reconnect immediately on foreground return after stale background sockets are torn down, so the app no longer stays disconnected until a later wake path happens. (#41384) Thanks @mbelinky.
- Gateway/Control UI: keep dashboard auth tokens in session-scoped browser storage so same-tab refreshes preserve remote token auth without restoring long-lived localStorage token persistence, while scoping tokens to the selected gateway URL and fragment-only bootstrap flow. (#40892) thanks @velvet-shark.
- Gateway/macOS launchd restarts: keep the LaunchAgent registered during explicit restarts, hand off self-restarts through a detached launchd helper, and recover config/hot reload restart paths without unloading the service. Fixes #43311, #43406, #43035, and #43049.
- macOS/LaunchAgent install: tighten LaunchAgent directory and plist permissions during install so launchd bootstrap does not fail when the target home path or generated plist inherited group/world-writable modes.
- Discord/reply chunking: resolve the effective
maxLinesPerMessageconfig across live reply paths and preservechunkModein the fast send path so long Discord replies no longer split unexpectedly at the default 17-line limit. (#40133) thanks @rbutera. - Feishu/local image auto-convert: pass
mediaLocalRootsthrough thesendTextlocal-image shim so allowed local image paths upload as Feishu images again instead of falling back to raw path text. (#40623) Thanks @ayanesakura. - Models/Kimi Coding: send
anthropic-messagestools in native Anthropic format again sokimi-codingstops degrading tool calls into XML/plain-text pseudo invocations instead of realtool_useblocks. (#38669, #39907, #40552) Thanks @opriz. - Telegram/outbound HTML sends: chunk long HTML-mode messages, preserve plain-text fallback and silent-delivery params across retries, and cut over to plain text when HTML chunk planning cannot safely preserve the full message. (#42240) thanks @obviyus.
- Telegram/final preview delivery: split active preview lifecycle from cleanup retention so missing archived preview edits avoid duplicate fallback sends without clearing the live preview or blocking later in-place finalization. (#41662) thanks @hougangdev.
- Telegram/final preview delivery followup: keep ambiguous missing-
message_idfinals only when a preview was already visible, while first-preview/no-id cases still fall back so Telegram users do not lose the final reply. (#41932) thanks @hougangdev. - Telegram/final preview cleanup follow-up: clear stale cleanup-retain state only for transient preview finals so archived-preview retains no longer leave a stale partial bubble beside a later fallback-sent final. (#41763) Thanks @obviyus.
- Gateway/auth: allow one trusted device-token retry on shared-token mismatch with recovery hints to prevent reconnect churn during token drift. (#42507) Thanks @joshavant.
- Gateway/config errors: surface up to three validation issues in top-level
config.set,config.patch, andconfig.applyerror messages while preserving structured issue details. (#42664) Thanks @huntharo. - Agents/Azure OpenAI Responses: include the
azure-openaiprovider in the Responses API store override so Azure OpenAI multi-turn cron jobs and embedded agent runs no longer fail with HTTP 400 "store is set to false". (#42934, fixes #42800) Thanks @ademczuk. - Agents/error rendering: ignore stale assistant
errorMessagefields on successful turns so background/tool-side failures no longer prepend synthetic billing errors over valid replies. (#40616) Thanks @ingyukoh. - Agents/billing recovery: probe single-provider billing cooldowns on the existing throttle so topping up credits can recover without a manual gateway restart. (#41422) thanks @altaywtf.
- Agents/fallback: treat HTTP 499 responses as transient in both raw-text and structured failover paths so Anthropic-style client-closed overload responses trigger model fallback reliably. (#41468) thanks @zeroasterisk.
- Agents/fallback: recognize Venice
402 Insufficient USD or Diem balancebilling errors so configured model fallbacks trigger instead of surfacing the raw provider error. (#43205) Thanks @Squabble9. - Agents/fallback: recognize Poe
402 You've used up your points!billing errors so configured model fallbacks trigger instead of surfacing the raw provider error. (#42278) Thanks @CryUshio. - Agents/failover: treat Gemini
MALFORMED_RESPONSEstop reasons as retryable timeouts so preview-model enum drift falls back cleanly instead of crashing the run, without also reclassifying malformed function-call errors. (#42292) Thanks @jnMetaCode. - Agents/cooldowns: default cooldown windows with no recorded failure history to
unknowninstead ofrate_limit, avoiding false API rate-limit warnings while preserving cooldown recovery probes. (#42911) Thanks @VibhorGautam. - Auth/cooldowns: reset expired auth-profile cooldown error counters before computing the next backoff so stale on-disk counters do not re-escalate into long cooldown loops after expiry. (#41028) thanks @zerone0x.
- Agents/memory flush: forward
memoryFlushWritePaththroughrunEmbeddedPiAgentso memory-triggered flush turns keep the append-only write guard without aborting before tool setup. Follows up on #38574. (#41761) Thanks @frankekn. - Agents/context pruning: prune image-only tool results during soft-trim, align context-pruning coverage with the new tool-result contract, and extend historical image cleanup to the same screenshot-heavy session path. (#43045) Thanks @MoerAI.
- Sessions/reset model recompute: clear stale runtime model, context-token, and system-prompt metadata before session resets recompute the replacement session, so resets pick up current defaults and explicit overrides instead of reusing old runtime model state. (#41173) thanks @PonyX-lab.
- Channels/allowlists: remove stale matcher caching so same-array allowlist edits and wildcard replacements take effect immediately, with regression coverage for in-place mutation cases.
- Discord/Telegram outbound runtime config: thread runtime-resolved config through Discord and Telegram send paths so SecretRef-based credentials stay resolved during message delivery. (#42352) Thanks @joshavant.
- Tools/web search: treat Brave
llm-contextgrounding snippets as plain strings soweb_searchno longer returns empty snippet arrays in LLM Context mode. (#41387) thanks @zheliu2. - Tools/web search: recover OpenRouter Perplexity citation extraction from
message.annotationswhen chat-completions responses omit top-level citations. (#40881) Thanks @laurieluo. - CLI/skills JSON: strip ANSI and C1 control bytes from
skills list --json,skills info --json, andskills check --jsonso machine-readable output stays valid for terminals and skill metadata with embedded control characters. Fixes #27530. Related #27557. Thanks @Jimmy-xuzimo and @vincentkoc. - CLI/tables: default shared tables to ASCII borders on legacy Windows consoles while keeping Unicode borders on modern Windows terminals, so commands like
openclaw skillsstop rendering mojibake under GBK/936 consoles. Fixes #40853. Related #41015. Thanks @ApacheBin and @vincentkoc. - CLI/memory teardown: close cached memory search/index managers in the one-shot CLI shutdown path so watcher-backed memory caches no longer keep completed CLI runs alive after output finishes. (#40389) thanks @Julbarth.
- Control UI/Sessions: restore single-column session table collapse on narrow viewport or container widths by moving the responsive table override next to the base grid rule and enabling inline-size container queries. (#12175) Thanks @benjipeng.
- Telegram/network env-proxy: apply configured transport policy to proxied HTTPS dispatchers as well as direct
NO_PROXYbypasses, so resolver-scoped IPv4 fallback and network settings work consistently for env-proxied Telegram traffic. (#40740) Thanks @sircrumpet. - Mattermost/Markdown formatting: preserve first-line indentation when stripping bot mentions so nested list items and indented code blocks keep their structure, and render Mattermost tables natively by default instead of fenced-code fallback. (#18655) thanks @echo931.
- Mattermost/plugin send actions: normalize direct
replyTofallback handling so threaded plugin sends trim blank IDs and reuse the correct reply target again. (#41176) Thanks @hnykda. - MS Teams/allowlist resolution: use the General channel conversation ID as the resolved team key (with Graph GUID fallback) so Bot Framework runtime
channelData.team.idmatching works for team and team/channel allowlist entries. (#41838) Thanks @BradGroux. - Signal/config schema: accept
channels.signal.accountUuidin strict config validation so loop-protection configs no longer fail with an unrecognized-key error. (#35578) Thanks @ingyukoh. - Telegram/config schema: accept
channels.telegram.actions.editMessageandcreateForumTopicin strict config validation so existing Telegram action toggles no longer fail as unrecognized keys. (#35498) Thanks @ingyukoh. - Telegram/docs: clarify that
channels.telegram.groupsallowlists chats whilegroupAllowFromallowlists users inside those chats, and point invalid negative chat IDs at the right config key. (#42451) Thanks @altaywtf. - Discord/config typing: expose channel-level
autoThreadon the canonical guild-channel config type so strict config loading matches the existing Discord schema and runtime behavior. (#35608) Thanks @ingyukoh. - fix(models): guard optional model.input capability checks (#42096) thanks @andyliu
- Models/Alibaba Cloud Model Studio: wire
MODELSTUDIO_API_KEYthrough shared env auth, implicit provider discovery, and shell-env fallback so onboarding works outside the wizard too. (#40634) Thanks @pomelo-nwu. - Resolve web tool SecretRefs atomically at runtime. (#41599) Thanks @joshavant.
- Secret files: harden CLI and channel credential file reads against path-swap races by requiring direct regular files for
*Filesecret inputs and rejecting symlink-backed secret files. - Archive extraction: harden TAR and external
tar.bz2installs against destination symlink and pre-existing child-symlink escapes by extracting into staging first and merging into the canonical destination with safe file opens. - Secrets/SecretRef: reject exec SecretRef traversal ids across schema, runtime, and gateway. (#42370) Thanks @joshavant.
- Sandbox/fs bridge: pin staged writes to verified parent directories so temporary write files cannot materialize outside the allowed mount before atomic replace. Thanks @tdjackey.
- Gateway/auth: fail closed when local
gateway.auth.*SecretRefs are configured but unavailable, instead of silently falling back togateway.remote.*credentials in local mode. (#42672) Thanks @joshavant. - Commands/config writes: enforce
configWritesagainst both the originating account and the targeted account scope for/configand config-backed/allowlistedits, blocking sibling-account mutations while preserving gatewayoperator.adminflows. Thanks @tdjackey for reporting. - Security/system.run: fail closed for approval-backed interpreter/runtime commands when OpenClaw cannot bind exactly one concrete local file operand, while extending best-effort direct-file binding to additional runtime forms. Thanks @tdjackey for reporting.
- Gateway/session reset auth: split conversation
/newand/resethandling away from the admin-onlysessions.resetcontrol-plane RPC so write-scoped gateway callers can no longer reach the privileged reset path throughagent. Thanks @tdjackey for reporting. - Security/plugin runtime: stop unauthenticated plugin HTTP routes from inheriting synthetic admin gateway scopes when they call
runtime.subagent.*, so admin-only methods likesessions.deletestay blocked without gateway auth. - Security/session_status: enforce sandbox session-tree visibility and shared agent-to-agent access guards before reading or mutating target session state, so sandboxed subagents can no longer inspect parent session metadata or write parent model overrides via
session_status. - Security/nodes: treat the
nodesagent tool as owner-only fallback policy so non-owner senders cannot reach paired-node approval or invoke paths through the shared tool set. - Security/external content: treat whitespace-delimited
EXTERNAL UNTRUSTED CONTENTboundary markers like underscore-delimited variants so prompt wrappers cannot bypass marker sanitization. (#35983) Thanks @urianpaul94. - Telegram/exec approvals: reject
/approvecommands aimed at other bots, keep deterministic approval prompts visible when tool-result delivery fails, and stop resolved exact IDs from matching other pending approvals by prefix. (#37233) Thanks @huntharo. - Subagents/authority: persist leaf vs orchestrator control scope at spawn time and route tool plus slash-command control through shared ownership checks, so leaf sessions cannot regain orchestration privileges after restore or flat-key lookups. Thanks @tdjackey.
- ACP/ACPX plugin: bump the bundled
acpxpin to0.1.16so plugin-local installs and strict version checks match the latest published CLI. (#41975) Thanks @dutifulbob. - ACP/sessions.patch: allow
spawnedByandspawnDepthlineage fields on ACP session keys sosessions_spawnwithruntime: "acp"no longer fails during child-session setup. Fixes #40971. (#40995) thanks @xaeon2026. - ACP/stop reason mapping: resolve gateway chat
state: "error"completions as ACPend_turninstead ofrefusalso transient backend failures are not surfaced as deliberate refusals. (#41187) thanks @pejmanjohn. - ACP/setSessionMode: propagate gateway
sessions.patchfailures back to ACP clients so rejected mode changes no longer return silent success. (#41185) thanks @pejmanjohn. - ACP/bridge mode: reject unsupported per-session MCP server setup and propagate rejected session-mode changes so IDE clients see explicit bridge limitations instead of silent success. (#41424) Thanks @mbelinky.
- ACP/session UX: replay stored user and assistant text on
loadSession, expose Gateway-backed session controls and metadata, and emit approximate session usage updates so IDE clients restore context more faithfully. (#41425) Thanks @mbelinky. - ACP/tool streaming: enrich
tool_callandtool_call_updateevents with best-effort text content and file-location hints so IDE clients can follow bridge tool activity more naturally. (#41442) Thanks @mbelinky. - ACP/runtime attachments: forward normalized inbound image attachments into ACP runtime turns so ACPX sessions can preserve image prompt content on the runtime path. (#41427) Thanks @mbelinky.
- ACP/regressions: add gateway RPC coverage for ACP lineage patching, ACPX runtime coverage for image prompt serialization, and an operator smoke-test procedure for live ACP spawn verification. (#41456) Thanks @mbelinky.
- ACP/follow-up hardening: make session restore and prompt completion degrade gracefully on transcript/update failures, enforce bounded tool-location traversal, and skip non-image ACPX turns the runtime cannot serialize. (#41464) Thanks @mbelinky.
- ACP/sessions_spawn: implicitly stream
mode="run"ACP spawns to parent only for eligible subagent orchestrator sessions (heartbeattarget: "last"with a usable session-local route), restoring parent progress relays without thread binding. (#42404) Thanks @davidguttman. - ACP/main session aliases: canonicalize
mainbefore ACP session lookup so restarted ACP main sessions rehydrate instead of failing closed withSession is not ACP-enabled: main. (#43285, fixes #25692) - Plugins/context-engine model auth: expose
runtime.modelAuthand plugin-sdk auth helpers so plugins can resolve provider/model API keys through the normal auth pipeline. (#41090) thanks @xinhuagu. - Hooks/plugin context parity followup: pass
triggerandchannelIdthrough embeddedllm_input,agent_end, andllm_outputhook contexts so plugins receive the same agent metadata across hook phases. (#42362) Thanks @zhoulf1006. - Plugins/global hook runner: harden singleton state handling so shared global hook runner reuse does not leak or corrupt runner state across executions. (#40184) Thanks @vincentkoc.
- Context engine/tests: add bundled-registry regression coverage for cross-chunk resolution, plugin-sdk re-exports, and concurrent chunk registration. (#40460) thanks @dsantoreis.
- Agents/embedded runner: bound compaction retry waiting and drain embedded runs during SIGUSR1 restart so session lanes recover instead of staying blocked behind compaction. (#40324) thanks @cgdusek.
- Agents/embedded logs: add structured, sanitized lifecycle and failover observation events so overload and provider failures are easier to tail and filter. (#41336) thanks @altaywtf.
- Agents/embedded overload logs: include the failing model and provider in error-path console output, with lifecycle regression coverage for the rendered and sanitized
consoleMessage. (#41236) thanks @jiarung. - Agents/fallback observability: add structured, sanitized model-fallback decision and auth-profile failure-state events with correlated run IDs so cooldown probes and failover paths are easier to trace in logs. (#41337) thanks @altaywtf.
- Logging/probe observations: suppress structured embedded and model-fallback probe warnings on the console without hiding error or fatal output. (#41338) thanks @altaywtf.
- Agents/context-engine compaction: guard thrown engine-owned overflow compaction attempts and fire compaction hooks for
ownsCompactionengines so overflow recovery no longer crashes and plugin subscribers still observe compact runs. (#41361) thanks @davidrudduck. - Gateway/node pending drain followup: keep
hasMoretrue when the deferred baseline status item still needs delivery, and avoid allocating empty pending-work state for drain-only nodes with no queued work. (#41429) Thanks @mbelinky. - Protocol/Swift model sync: regenerate pending node work Swift bindings after the landed
node.pending.*schema additions so generated protocol artifacts are consistent again. (#41477) Thanks @mbelinky. - Cron/subagent followup: do not misclassify empty or
NO_REPLYcron responses as interim acknowledgements that need a rerun, so deliberately silent cron jobs are no longer retried. (#41383) thanks @jackal092927. - Cron/state errors: record
lastErrorReasonin cron job state and keep the gateway schema aligned with the full failover-reason set, including regression coverage for protocol conformance. (#14382) thanks @futuremind2026. - Browser/Browserbase 429 handling: surface stable no-retry rate-limit guidance without buffering discarded HTTP 429 response bodies from remote browser services. (#40491) thanks @mvanhorn.
- CI/CodeQL Swift toolchain: select Xcode 26.1 before installing Swift build tools so the CodeQL Swift job uses Swift tools 6.2 on
macos-latest. (#41787) thanks @BunsDev. - Sandbox/subagents: pass the real configured workspace through
sessions_spawninheritance when a parent agent runs in a copied-workspace sandbox, so child/agentmounts point at the configured workspace instead of the parent sandbox copy. (#40757) Thanks @dsantoreis. - Agents/fallback cooldown probing: cap cooldown-bypass probing to one attempt per provider per fallback run so multi-model same-provider cooldown chains can continue to cross-provider fallbacks instead of repeatedly stalling on duplicate cooldown probes. (#41711) Thanks @cgdusek.
- Telegram/direct delivery: bridge direct delivery sends to internal
message:senthooks so internal hook listeners observe successful Telegram deliveries. (#40185) Thanks @vincentkoc. - Dependencies: refresh workspace dependencies except the pinned Carbon package, and harden ACP session-config writes against non-string SDK values so newer ACP clients fail fast instead of tripping type/runtime mismatches.
- Telegram/polling restarts: clear bounded cleanup timeout handles after
runner.stop()andbot.stop()settle so stall recovery no longer leaves stray 15-second timers behind on clean shutdown. (#43188) thanks @kyohwang.