chore: update appcast for 2026.2.22 beta.1

This commit is contained in:
Peter Steinberger
2026-02-23 01:52:53 +01:00
parent 80f430c2be
commit b482da8c9a

View File

@@ -209,155 +209,251 @@
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.2.15/OpenClaw-2026.2.15.zip" length="22896513" type="application/octet-stream" sparkle:edSignature="MLGsd2NeHXFRH1Or0bFQnAjqfuuJDuhl1mvKFIqTQcRvwbeyvOyyLXrqSbmaOgJR3wBQBKLs6jYQ9dQ/3R8RCg=="/>
</item>
<item>
<title>2026.2.21</title>
<pubDate>Sat, 21 Feb 2026 17:55:48 +0100</pubDate>
<title>2026.2.22</title>
<pubDate>Mon, 23 Feb 2026 01:51:13 +0100</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>13056</sparkle:version>
<sparkle:shortVersionString>2026.2.21</sparkle:shortVersionString>
<sparkle:version>14126</sparkle:version>
<sparkle:shortVersionString>2026.2.22</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.2.21</h2>
<description><![CDATA[<h2>OpenClaw 2026.2.22</h2>
<h3>Changes</h3>
<ul>
<li>Models/Google: add Gemini 3.1 support (<code>google/gemini-3.1-pro-preview</code>).</li>
<li>Providers/Onboarding: add Volcano Engine (Doubao) and BytePlus providers/models (including coding variants), wire onboarding auth choices for interactive + non-interactive flows, and align docs to <code>volcengine-api-key</code>. (#7967) Thanks @funmore123.</li>
<li>Channels/CLI: add per-account/channel <code>defaultTo</code> outbound routing fallback so <code>openclaw agent --deliver</code> can send without explicit <code>--reply-to</code> when a default target is configured. (#16985) Thanks @KirillShchetinin.</li>
<li>Channels: allow per-channel model overrides via <code>channels.modelByChannel</code> and note them in /status. Thanks @thewilloftheshadow.</li>
<li>Telegram/Streaming: simplify preview streaming config to <code>channels.telegram.streaming</code> (boolean), auto-map legacy <code>streamMode</code> values, and remove block-vs-partial preview branching. (#22012) thanks @obviyus.</li>
<li>Discord/Streaming: add stream preview mode for live draft replies with partial/block options and configurable chunking. Thanks @thewilloftheshadow. Inspiration @neoagentic-ship-it.</li>
<li>Discord/Telegram: add configurable lifecycle status reactions for queued/thinking/tool/done/error phases with a shared controller and emoji/timing overrides. Thanks @wolly-tundracube and @thewilloftheshadow.</li>
<li>Discord/Voice: add voice channel join/leave/status via <code>/vc</code>, plus auto-join configuration for realtime voice conversations. Thanks @thewilloftheshadow.</li>
<li>Discord: add configurable ephemeral defaults for slash-command responses. (#16563) Thanks @wei.</li>
<li>Discord: support updating forum <code>available_tags</code> via channel edit actions for forum tag management. (#12070) Thanks @xiaoyaner0201.</li>
<li>Discord: include channel topics in trusted inbound metadata on new sessions. Thanks @thewilloftheshadow.</li>
<li>Discord/Subagents: add thread-bound subagent sessions on Discord with per-thread focus/list controls and thread-bound continuation routing for spawned helper agents. (#21805) Thanks @onutc.</li>
<li>iOS/Chat: clean chat UI noise by stripping inbound untrusted metadata/timestamp prefixes, formatting tool outputs into concise summaries/errors, compacting the composer while typing, and supporting tap-to-dismiss keyboard in chat view. (#22122) thanks @mbelinky.</li>
<li>iOS/Watch: bridge mirrored watch prompt notification actions into iOS quick-reply handling, including queued action handoff until app model initialization. (#22123) thanks @mbelinky.</li>
<li>iOS/Gateway: stabilize background wake and reconnect behavior with background reconnect suppression/lease windows, BGAppRefresh wake fallback, location wake hook throttling, and APNs wake retry+nudge instrumentation. (#21226) thanks @mbelinky.</li>
<li>Auto-reply/UI: add model fallback lifecycle visibility in verbose logs, /status active-model context with fallback reason, and cohesive WebUI fallback indicators. (#20704) Thanks @joshavant.</li>
<li>MSTeams: dedupe sent-message cache storage by removing duplicate per-message Set storage and using timestamps Map keys as the single membership source. (#22514) Thanks @TaKO8Ki.</li>
<li>Agents/Subagents: default subagent spawn depth now uses shared <code>maxSpawnDepth=2</code>, enabling depth-1 orchestrator spawning by default while keeping depth policy checks consistent across spawn and prompt paths. (#22223) Thanks @tyler6204.</li>
<li>Security/Agents: make owner-ID obfuscation use a dedicated HMAC secret from configuration (<code>ownerDisplaySecret</code>) and update hashing behavior so obfuscation is decoupled from gateway token handling for improved control. (#7343) Thanks @vincentkoc.</li>
<li>Security/Infra: switch gateway lock and tool-call synthetic IDs from SHA-1 to SHA-256 with unchanged truncation length to strengthen hash basis while keeping deterministic behavior and lock key format. (#7343) Thanks @vincentkoc.</li>
<li>Dependencies/Tooling: add non-blocking dead-code scans in CI via Knip/ts-prune/ts-unused-exports to surface unused dependencies and exports earlier. (#22468) Thanks @vincentkoc.</li>
<li>Dependencies/Unused Dependencies: remove or scope unused root and extension deps (<code>@larksuiteoapi/node-sdk</code>, <code>signal-utils</code>, <code>ollama</code>, <code>lit</code>, <code>@lit/context</code>, <code>@lit-labs/signals</code>, <code>@microsoft/agents-hosting-express</code>, <code>@microsoft/agents-hosting-extensions-teams</code>, and plugin-local <code>openclaw</code> devDeps in <code>extensions/open-prose</code>, <code>extensions/lobster</code>, and <code>extensions/llm-task</code>). (#22471, #22495) Thanks @vincentkoc.</li>
<li>Dependencies/A2UI: harden dependency resolution after root cleanup (resolve <code>lit</code>, <code>@lit/context</code>, <code>@lit-labs/signals</code>, and <code>signal-utils</code> from workspace/root) and simplify bundling fallback behavior, including <code>pnpm dlx rolldown</code> compatibility. (#22481, #22507) Thanks @vincentkoc.</li>
<li>Provider/Mistral: add support for the Mistral provider, including memory embeddings and voice support. (#23845) Thanks @vincentkoc.</li>
<li>Update/Core: add an optional built-in auto-updater for package installs (<code>update.auto.*</code>), default-off, with stable rollout delay+jitter and beta hourly cadence.</li>
<li>CLI/Update: add <code>openclaw update --dry-run</code> to preview channel/tag/target/restart actions without mutating config, installing, syncing plugins, or restarting.</li>
<li>Config/UI: add tag-aware settings filtering and broaden config labels/help copy so fields are easier to discover and understand in the dashboard config screen.</li>
<li>Channels/Synology Chat: add a native Synology Chat channel plugin with webhook ingress, direct-message routing, outbound send/media support, per-account config, and DM policy controls. (#23012)</li>
<li>iOS/Talk: prefetch TTS segments and suppress expected speech-cancellation errors for smoother talk playback. (#22833) Thanks @ngutman.</li>
<li>Memory/FTS: add Spanish and Portuguese stop-word filtering for query expansion in FTS-only search mode, improving conversational recall for both languages. Thanks @vincentkoc.</li>
<li>Memory/FTS: add Japanese-aware query expansion tokenization and stop-word filtering (including mixed-script terms like ASCII + katakana) for FTS-only search mode. Thanks @vincentkoc.</li>
<li>Memory/FTS: add Korean stop-word filtering and particle-aware keyword extraction (including mixed Korean/English stems) for query expansion in FTS-only search mode. (#18899) Thanks @ruypang.</li>
<li>Memory/FTS: add Arabic stop-word filtering for query expansion in FTS-only search mode to reduce conversational filler in Arabic memory searches. Thanks @vincentkoc.</li>
<li>Discord/Allowlist: canonicalize resolved Discord allowlist names to IDs and split resolution flow for clearer fail-closed behavior.</li>
<li>Channels/Config: unify channel preview streaming config handling with a shared resolver and canonical migration path.</li>
<li>Gateway/Auth: unify call/probe/status/auth credential-source precedence on shared resolver helpers, with table-driven parity coverage across gateway entrypoints.</li>
<li>Gateway/Auth: refactor gateway credential resolution and websocket auth handshake paths to use shared typed auth contexts, including explicit <code>auth.deviceToken</code> support in connect frames and tests.</li>
<li>Skills: remove bundled <code>food-order</code> skill from this repo; manage/install it from ClawHub instead.</li>
<li>Docs/Subagents: make thread-bound session guidance channel-first instead of Discord-specific, and list thread-supporting channels explicitly. (#23589) Thanks @osolmaz.</li>
</ul>
<h3>Breaking</h3>
<ul>
<li><strong>BREAKING:</strong> tool-failure replies now hide raw error details by default. OpenClaw still sends a failure summary, but detailed error suffixes (for example provider/runtime messages and local path fragments) now require <code>/verbose on</code> or <code>/verbose full</code>.</li>
<li><strong>BREAKING:</strong> CLI local onboarding now sets <code>session.dmScope</code> to <code>per-channel-peer</code> by default for new/implicit DM scope configuration. If you depend on shared DM continuity across senders, explicitly set <code>session.dmScope</code> to <code>main</code>. (#23468) Thanks @bmendonca3.</li>
<li><strong>BREAKING:</strong> unify channel preview-streaming config to <code>channels.<channel>.streaming</code> with enum values <code>off | partial | block | progress</code>, and move Slack native stream toggle to <code>channels.slack.nativeStreaming</code>. Legacy keys (<code>streamMode</code>, Slack boolean <code>streaming</code>) are still read and migrated by <code>openclaw doctor --fix</code>, but canonical saved config/docs now use the unified names.</li>
<li><strong>BREAKING:</strong> remove legacy Gateway device-auth signature <code>v1</code>. Device-auth clients must now sign <code>v2</code> payloads with the per-connection <code>connect.challenge</code> nonce and send <code>device.nonce</code>; nonce-less connects are rejected.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Security/Agents: cap embedded Pi runner outer retry loop with a higher profile-aware dynamic limit (32-160 attempts) and return an explicit <code>retry_limit</code> error payload when retries never converge, preventing unbounded internal retry cycles (<code>GHSA-76m6-pj3w-v7mf</code>).</li>
<li>Telegram: detect duplicate bot-token ownership across Telegram accounts at startup/status time, mark secondary accounts as not configured with an explicit fix message, and block duplicate account startup before polling to avoid endless <code>getUpdates</code> conflict loops.</li>
<li>Agents/Tool images: include source filenames in <code>agents/tool-images</code> resize logs so compression events can be traced back to specific files.</li>
<li>Providers/OAuth: harden Qwen and Chutes refresh handling by validating refresh response expiry values and preserving prior refresh tokens when providers return empty refresh token fields, with regression coverage for empty-token responses.</li>
<li>Models/Kimi-Coding: add missing implicit provider template for <code>kimi-coding</code> with correct <code>anthropic-messages</code> API type and base URL, fixing 403 errors when using Kimi for Coding. (#22409)</li>
<li>Auto-reply/Tools: forward <code>senderIsOwner</code> through embedded queued/followup runner params so owner-only tools remain available for authorized senders. (#22296) thanks @hcoj.</li>
<li>Discord: restore model picker back navigation when a provider is missing and document the Discord picker flow. (#21458) Thanks @pejmanjohn and @thewilloftheshadow.</li>
<li>Memory/QMD: respect per-agent <code>memorySearch.enabled=false</code> during gateway QMD startup initialization, split multi-collection QMD searches into per-collection queries (<code>search</code>/<code>vsearch</code>/<code>query</code>) to avoid sparse-term drops, prefer collection-hinted doc resolution to avoid stale-hash collisions, retry boot updates on transient lock/timeout failures, skip <code>qmd embed</code> in BM25-only <code>search</code> mode (including <code>memory index --force</code>), and serialize embed runs globally with failure backoff to prevent CPU storms on multi-agent hosts. (#20581, #21590, #20513, #20001, #21266, #21583, #20346, #19493) Thanks @danielrevivo, @zanderkrause, @sunyan034-cmd, @tilleulenspiegel, @dae-oss, @adamlongcreativellc, @jonathanadams96, and @kiliansitel.</li>
<li>Memory/Builtin: prevent automatic sync races with manager shutdown by skipping post-close sync starts and waiting for in-flight sync before closing SQLite, so <code>onSearch</code>/<code>onSessionStart</code> no longer fail with <code>database is not open</code> in ephemeral CLI flows. (#20556, #7464) Thanks @FuzzyTG and @henrybottter.</li>
<li>Providers/Copilot: drop persisted assistant <code>thinking</code> blocks for Claude models (while preserving turn structure/tool blocks) so follow-up requests no longer fail on invalid <code>thinkingSignature</code> payloads. (#19459) Thanks @jackheuberger.</li>
<li>Providers/Copilot: add <code>claude-sonnet-4.6</code> and <code>claude-sonnet-4.5</code> to the default GitHub Copilot model catalog and add coverage for model-list/definition helpers. (#20270, fixes #20091) Thanks @Clawborn.</li>
<li>Auto-reply/WebChat: avoid defaulting inbound runtime channel labels to unrelated providers (for example <code>whatsapp</code>) for webchat sessions so channel-specific formatting guidance stays accurate. (#21534) Thanks @lbo728.</li>
<li>Status: include persisted <code>cacheRead</code>/<code>cacheWrite</code> in session summaries so compact <code>/status</code> output consistently shows cache hit percentages from real session data.</li>
<li>Heartbeat/Cron: restore interval heartbeat behavior so missing <code>HEARTBEAT.md</code> no longer suppresses runs (only effectively empty files skip), preserving prompt-driven and tagged-cron execution paths.</li>
<li>WhatsApp/Cron/Heartbeat: enforce allowlisted routing for implicit scheduled/system delivery by merging pairing-store + configured <code>allowFrom</code> recipients, selecting authorized recipients when last-route context points to a non-allowlisted chat, and preventing heartbeat fan-out to recent unauthorized chats.</li>
<li>Heartbeat/Active hours: constrain active-hours <code>24</code> sentinel parsing to <code>24:00</code> in time validation so invalid values like <code>24:30</code> are rejected early. (#21410) thanks @adhitShet.</li>
<li>Heartbeat: treat <code>activeHours</code> windows with identical <code>start</code>/<code>end</code> times as zero-width (always outside the window) instead of always-active. (#21408) thanks @adhitShet.</li>
<li>CLI/Pairing: default <code>pairing list</code> and <code>pairing approve</code> to the sole available pairing channel when omitted, so TUI-only setups can recover from <code>pairing required</code> without guessing channel arguments. (#21527) Thanks @losts1.</li>
<li>TUI/Pairing: show explicit pairing-required recovery guidance after gateway disconnects that return <code>pairing required</code>, including approval steps to unblock quickstart TUI hatching on fresh installs. (#21841) Thanks @nicolinux.</li>
<li>TUI/Input: suppress duplicate backspace events arriving in the same input burst window so SSH sessions no longer delete two characters per backspace press in the composer. (#19318) Thanks @eheimer.</li>
<li>TUI/Heartbeat: suppress heartbeat ACK/prompt noise in chat streaming when <code>showOk</code> is disabled, while still preserving non-ACK heartbeat alerts in final output. (#20228) Thanks @bhalliburton.</li>
<li>TUI/History: cap chat-log component growth and prune stale render nodes/references so large default history loads no longer overflow render recursion with <code>RangeError: Maximum call stack size exceeded</code>. (#18068) Thanks @JaniJegoroff.</li>
<li>Memory/QMD: diversify mixed-source search ranking when both session and memory collections are present so session transcript hits no longer crowd out durable memory-file matches in top results. (#19913) Thanks @alextempr.</li>
<li>Memory/Tools: return explicit <code>unavailable</code> warnings/actions from <code>memory_search</code> when embedding/provider failures occur (including quota exhaustion), so disabled memory does not look like an empty recall result. (#21894) Thanks @XBS9.</li>
<li>Session/Startup: require the <code>/new</code> and <code>/reset</code> greeting path to run Session Startup file-reading instructions before responding, so daily memory startup context is not skipped on fresh-session greetings. (#22338) Thanks @armstrong-pv.</li>
<li>Auth/Onboarding: align OAuth profile-id config mapping with stored credential IDs for OpenAI Codex and Chutes flows, preventing <code>provider:default</code> mismatches when OAuth returns email-scoped credentials. (#12692) thanks @mudrii.</li>
<li>Provider/HTTP: treat HTTP 503 as failover-eligible for LLM provider errors. (#21086) Thanks @Protocol-zero-0.</li>
<li>Slack: pass <code>recipient_team_id</code> / <code>recipient_user_id</code> through Slack native streaming calls so <code>chat.startStream</code>/<code>appendStream</code>/<code>stopStream</code> work reliably across DMs and Slack Connect setups, and disable block streaming when native streaming is active. (#20988) Thanks @Dithilli. Earlier recipient-ID groundwork was contributed in #20377 by @AsserAl1012.</li>
<li>CLI/Config: add canonical <code>--strict-json</code> parsing for <code>config set</code> and keep <code>--json</code> as a legacy alias to reduce help/behavior drift. (#21332) thanks @adhitShet.</li>
<li>CLI: keep <code>openclaw -v</code> as a root-only version alias so subcommand <code>-v, --verbose</code> flags (for example ACP/hooks/skills) are no longer intercepted globally. (#21303) thanks @adhitShet.</li>
<li>Memory: return empty snippets when <code>memory_get</code>/QMD read files that have not been created yet, and harden memory indexing/session helpers against ENOENT races so missing Markdown no longer crashes tools. (#20680) Thanks @pahdo.</li>
<li>Telegram/Streaming: always clean up draft previews even when dispatch throws before fallback handling, preventing orphaned preview messages during failed runs. (#19041) thanks @mudrii.</li>
<li>Telegram/Streaming: split reasoning and answer draft preview lanes to prevent cross-lane overwrites, and ignore literal <code><think></code> tags inside inline/fenced code snippets so sample markup is not misrouted as reasoning. (#20774) Thanks @obviyus.</li>
<li>Telegram/Streaming: restore 30-char first-preview debounce and scope <code>NO_REPLY</code> prefix suppression to partial sentinel fragments so normal <code>No...</code> text is not filtered. (#22613) thanks @obviyus.</li>
<li>Telegram/Status reactions: refresh stall timers on repeated phase updates and honor ack-reaction scope when lifecycle reactions are enabled, preventing false stall emojis and unwanted group reactions. Thanks @wolly-tundracube and @thewilloftheshadow.</li>
<li>Telegram/Status reactions: keep lifecycle reactions active when available-reactions lookup fails by falling back to unrestricted variant selection instead of suppressing reaction updates. (#22380) thanks @obviyus.</li>
<li>Discord/Streaming: apply <code>replyToMode: first</code> only to the first Discord chunk so block-streamed replies do not spam mention pings. (#20726) Thanks @thewilloftheshadow for the report.</li>
<li>Discord/Components: map DM channel targets back to user-scoped component sessions so button/select interactions stay in the main DM session. Thanks @thewilloftheshadow.</li>
<li>Discord/Allowlist: lazy-load guild lists when resolving Discord user allowlists so ID-only entries resolve even if guild fetch fails. (#20208) Thanks @zhangjunmengyang.</li>
<li>Discord/Gateway: handle close code 4014 (missing privileged gateway intents) without crashing the gateway. Thanks @thewilloftheshadow.</li>
<li>Discord: ingest inbound stickers as media so sticker-only messages and forwarded stickers are visible to agents. Thanks @thewilloftheshadow.</li>
<li>Auto-reply/Runner: emit <code>onAgentRunStart</code> only after agent lifecycle or tool activity begins (and only once per run), so fallback preflight errors no longer mark runs as started. (#21165) Thanks @shakkernerd.</li>
<li>Auto-reply/Tool results: serialize tool-result delivery and keep the delivery chain progressing after individual failures so concurrent tool outputs preserve user-visible ordering. (#21231) thanks @ahdernasr.</li>
<li>Auto-reply/Prompt caching: restore prefix-cache stability by keeping inbound system metadata session-stable and moving per-message IDs (<code>message_id</code>, <code>message_id_full</code>, <code>reply_to_id</code>, <code>sender_id</code>) into untrusted conversation context. (#20597) Thanks @anisoptera.</li>
<li>iOS/Watch: add actionable watch approval/reject controls and quick-reply actions so watch-originated approvals and responses can be sent directly from notification flows. (#21996) Thanks @mbelinky.</li>
<li>iOS/Watch: refresh iOS and watch app icon assets with the lobster icon set to keep phone/watch branding aligned. (#21997) Thanks @mbelinky.</li>
<li>CLI/Onboarding: fix Anthropic-compatible custom provider verification by normalizing base URLs to avoid duplicate <code>/v1</code> paths during setup checks. (#21336) Thanks @17jmumford.</li>
<li>iOS/Gateway/Tools: prefer uniquely connected node matches when duplicate display names exist, surface actionable <code>nodes invoke</code> pairing-required guidance with request IDs, and refresh active iOS gateway registration after location-capability setting changes so capability updates apply immediately. (#22120) thanks @mbelinky.</li>
<li>Gateway/Auth: require <code>gateway.trustedProxies</code> to include a loopback proxy address when <code>auth.mode="trusted-proxy"</code> and <code>bind="loopback"</code>, preventing same-host proxy misconfiguration from silently blocking auth. (#22082, follow-up to #20097) thanks @mbelinky.</li>
<li>Gateway/Auth: allow trusted-proxy mode with loopback bind for same-host reverse-proxy deployments, while still requiring configured <code>gateway.trustedProxies</code>. (#20097) thanks @xinhuagu.</li>
<li>Gateway/Auth: allow authenticated clients across roles/scopes to call <code>health</code> while preserving role and scope enforcement for non-health methods. (#19699) thanks @Nachx639.</li>
<li>Gateway/Hooks: include transform export name in hook-transform cache keys so distinct exports from the same module do not reuse the wrong cached transform function. (#13855) thanks @mcaxtr.</li>
<li>Gateway/Control UI: return 404 for missing static-asset paths instead of serving SPA fallback HTML, while preserving client-route fallback behavior for extensionless and non-asset dotted paths. (#12060) thanks @mcaxtr.</li>
<li>Gateway/Pairing: prevent device-token rotate scope escalation by enforcing an approved-scope baseline, preserving approved scopes across metadata updates, and rejecting rotate requests that exceed approved role scope implications. (#20703) thanks @coygeek.</li>
<li>Gateway/Pairing: clear persisted paired-device state when the gateway client closes with <code>device token mismatch</code> (<code>1008</code>) so reconnect flows can cleanly re-enter pairing. (#22071) Thanks @mbelinky.</li>
<li>Gateway/Config: allow <code>gateway.customBindHost</code> in strict config validation when <code>gateway.bind="custom"</code> so valid custom bind-host configurations no longer fail startup. (#20318, fixes #20289) Thanks @MisterGuy420.</li>
<li>Gateway/Pairing: tolerate legacy paired devices missing <code>roles</code>/<code>scopes</code> metadata in websocket upgrade checks and backfill metadata on reconnect. (#21447, fixes #21236) Thanks @joshavant.</li>
<li>Gateway/Pairing/CLI: align read-scope compatibility in pairing/device-token checks and add local <code>openclaw devices</code> fallback recovery for loopback <code>pairing required</code> deadlocks, with explicit fallback notice to unblock approval bootstrap flows. (#21616) Thanks @shakkernerd.</li>
<li>Security/CLI: redact sensitive values in <code>openclaw config get</code> output before printing config paths, preventing credential leakage to terminal output/history. (#13683) Thanks @SleuthCo.</li>
<li>Install/Discord Voice: make <code>@discordjs/opus</code> an optional dependency so <code>openclaw</code> install/update no longer hard-fails when native Opus builds fail, while keeping <code>opusscript</code> as the runtime fallback decoder for Discord voice flows. (#23737, #23733, #23703) Thanks @jeadland, @Sheetaa, and @Breakyman.</li>
<li>Docker/Setup: precreate <code>$OPENCLAW_CONFIG_DIR/identity</code> during <code>docker-setup.sh</code> so CLI commands that need device identity (for example <code>devices list</code>) avoid <code>EACCES ... /home/node/.openclaw/identity</code> failures on restrictive bind mounts. (#23948) Thanks @ackson-beep.</li>
<li>Exec/Background: stop applying the default exec timeout to background sessions (<code>background: true</code> or explicit <code>yieldMs</code>) when no explicit timeout is set, so long-running background jobs are no longer terminated at the default timeout boundary. (#23303)</li>
<li>Slack/Threading: sessions: keep parent-session forking and thread-history context active beyond first turn by removing first-turn-only gates in session init, thread-history fetch, and reply prompt context injection. (#23843, #23090) Thanks @vincentkoc and @Taskle.</li>
<li>Slack/Threading: respect <code>replyToMode</code> when Slack auto-populates top-level <code>thread_ts</code>, and ignore inline <code>replyToId</code> directive tags when <code>replyToMode</code> is <code>off</code> so thread forcing stays disabled unless explicitly configured. (#23839, #23320, #23513) Thanks @vincentkoc and @dorukardahan.</li>
<li>Slack/Extension: forward <code>message read</code> <code>threadId</code> to <code>readMessages</code> and use delivery-context <code>threadId</code> as outbound <code>thread_ts</code> fallback so extension replies/reads stay in the correct Slack thread. (#22216, #22485, #23836) Thanks @vincentkoc, @lan17 and @dorukardahan.</li>
<li>Slack/Upload: resolve bare user IDs (U-prefix) to DM channel IDs via <code>conversations.open</code> before calling <code>files.uploadV2</code>, which rejects non-channel IDs. <code>chat.postMessage</code> tolerates user IDs directly, but <code>files.uploadV2</code> → <code>completeUploadExternal</code> validates <code>channel_id</code> against <code>^[CGDZ][A-Z0-9]{8,}$</code>, causing <code>invalid_arguments</code> when agents reply with media to DM conversations.</li>
<li>Webchat/Chat: apply assistant <code>final</code> payload messages directly to chat state so sent turns render without waiting for a full history refresh cycle. (#14928) Thanks @BradGroux.</li>
<li>Webchat/Chat: for out-of-band final events (for example tool-call side runs), append provided final assistant payloads directly instead of forcing a transient history reset. (#11139) Thanks @AkshayNavle.</li>
<li>Webchat/Performance: reload <code>chat.history</code> after final events only when the final payload lacks a renderable assistant message, avoiding expensive full-history refreshes on normal turns. (#20588) Thanks @amzzzzzzz.</li>
<li>Webchat/Sessions: preserve external session routing metadata when internal <code>chat.send</code> turns run under <code>webchat</code>, so explicit channel-keyed sessions (for example Telegram) no longer get rewritten to <code>webchat</code> and misroute follow-up delivery. (#23258) Thanks @binary64.</li>
<li>Webchat/Sessions: preserve existing session <code>label</code> across <code>/new</code> and <code>/reset</code> rollovers so reset sessions remain discoverable in session history lists. (#23755) Thanks @ThunderStormer.</li>
<li>Gateway/Chat UI: strip inline reply/audio directive tags from non-streaming final webchat broadcasts (including <code>chat.inject</code>) while preserving empty-string message content when tags are the entire reply. (#23298) Thanks @SidQin-cyber.</li>
<li>Chat/UI: strip inline reply/audio directive tags (<code>[[reply_to_current]]</code>, <code>[[reply_to:<id>]]</code>, <code>[[audio_as_voice]]</code>) from displayed chat history, live chat event output, and session preview snippets so control tags no longer leak into user-visible surfaces.</li>
<li>Telegram/Media: send a user-facing Telegram reply when media download fails (non-size errors) instead of silently dropping the message.</li>
<li>Telegram/Webhook: keep webhook monitors alive until gateway abort signals fire, preventing false channel exits and immediate webhook auto-restart loops.</li>
<li>Telegram/Polling: retry recoverable setup-time network failures in monitor startup and await runner teardown before retry to avoid overlapping polling sessions.</li>
<li>Telegram/Polling: clear Telegram webhooks (<code>deleteWebhook</code>) before starting long-poll <code>getUpdates</code>, including retry handling for transient cleanup failures.</li>
<li>Telegram/Webhook: add <code>channels.telegram.webhookPort</code> config support and pass it through plugin startup wiring to the monitor listener.</li>
<li>Browser/Extension Relay: refactor the MV3 worker to preserve debugger attachments across relay drops, auto-reconnect with bounded backoff+jitter, persist and rehydrate attached tab state via <code>chrome.storage.session</code>, recover from <code>target_closed</code> navigation detaches, guard stale socket handlers, enforce per-tab operation locks and per-request timeouts, and add lifecycle keepalive/badge refresh hooks (<code>alarms</code>, <code>webNavigation</code>). (#15099, #6175, #8468, #9807)</li>
<li>Browser/Relay: treat extension websocket as connected only when <code>OPEN</code>, allow reconnect when a stale <code>CLOSING/CLOSED</code> extension socket lingers, and guard stale socket message/close handlers so late events cannot clear active relay state; includes regression coverage for live-duplicate <code>409</code> rejection and immediate reconnect-after-close races. (#15099, #18698, #20688)</li>
<li>Browser/Remote CDP: extend stale-target recovery so <code>ensureTabAvailable()</code> now reuses the sole available tab for remote CDP profiles (same behavior as extension profiles) while preserving strict <code>tab not found</code> errors when multiple tabs exist; includes remote-profile regression tests. (#15989)</li>
<li>Gateway/Pairing: treat <code>operator.admin</code> as satisfying other <code>operator.*</code> scope checks during device-auth verification so local CLI/TUI sessions stop entering pairing-required loops for pairing/approval-scoped commands. (#22062, #22193, #21191) Thanks @Botaccess, @jhartshorn, and @ctbritt.</li>
<li>Gateway/Pairing: auto-approve loopback <code>scope-upgrade</code> pairing requests (including device-token reconnects) so local clients do not disconnect on pairing-required scope elevation. (#23708) Thanks @widingmarcus-cyber.</li>
<li>Gateway/Scopes: include <code>operator.read</code> and <code>operator.write</code> in default operator connect scope bundles across CLI, Control UI, and macOS clients so write-scoped announce/sub-agent follow-up calls no longer hit <code>pairing required</code> disconnects on loopback gateways. (#22582) thanks @YuzuruS.</li>
<li>Gateway/Pairing: treat operator.admin pairing tokens as satisfying operator.write requests so legacy devices stop looping through scope-upgrade prompts introduced in 2026.2.19. (#23125, #23006) Thanks @vignesh07.</li>
<li>Gateway/Restart: fix restart-loop edge cases by keeping <code>openclaw.mjs -> dist/entry.js</code> bootstrap detection explicit, reacquiring the gateway lock for in-process restart fallback paths, and tightening restart-loop regression coverage. (#23416) Thanks @jeffwnli.</li>
<li>Gateway/Lock: use optional gateway-port reachability as a primary stale-lock liveness signal (and wire gateway run-loop lock acquisition to the resolved port), reducing false "already running" lockouts after unclean exits. (#23760) Thanks @Operative-001.</li>
<li>Delivery/Queue: quarantine queue entries immediately on known permanent delivery errors (for example invalid recipients or missing conversation references) by moving them to <code>failed/</code> instead of retrying on every restart. (#23794) Thanks @aldoeliacim.</li>
<li>Cron/Status: split execution outcome (<code>lastRunStatus</code>) from delivery outcome (<code>lastDeliveryStatus</code>) in persisted cron state, finished events, and run history so failed/unknown announcement delivery is visible without conflating it with run errors.</li>
<li>Cron/Delivery: route text-only announce jobs with explicit thread/topic targets through direct outbound delivery so forum/thread destinations do not get dropped by intermediary announce turns. (#23841) Thanks @AndrewArto.</li>
<li>Cron: honor <code>cron.maxConcurrentRuns</code> in the timer loop so due jobs can execute up to the configured parallelism instead of always running serially. (#11595) Thanks @Takhoffman.</li>
<li>Cron/Run: enforce the same per-job timeout guard for manual <code>cron.run</code> executions as timer-driven runs, including abort propagation for isolated agent jobs, so forced runs cannot wedge indefinitely. (#23704) Thanks @tkuehnl.</li>
<li>Cron/Run: persist the manual-run <code>runningAtMs</code> marker before releasing the cron lock so overlapping timer ticks cannot start the same job concurrently.</li>
<li>Cron/Startup: enforce per-job timeout guards for startup catch-up replay runs so missed isolated jobs cannot hang indefinitely during gateway boot recovery.</li>
<li>Cron/Main session: honor abort/timeout signals while retrying <code>wakeMode=now</code> heartbeat contention loops so main-target cron runs stop promptly instead of waiting through the full busy-retry window.</li>
<li>Cron/Schedule: for <code>every</code> jobs, prefer <code>lastRunAtMs + everyMs</code> when still in the future after restarts, then fall back to anchor scheduling for catch-up windows, so NEXT timing matches the last successful cadence. (#22895) Thanks @SidQin-cyber.</li>
<li>Cron/Service: execute manual <code>cron.run</code> jobs outside the cron lock (while still persisting started/finished state atomically) so <code>cron.list</code> and <code>cron.status</code> remain responsive during long forced runs. (#23628) Thanks @dsgraves.</li>
<li>Cron/Timer: keep a watchdog recheck timer armed while <code>onTimer</code> is actively executing so the scheduler continues polling even if a due-run tick stalls for an extended period. (#23628) Thanks @dsgraves.</li>
<li>Cron/Run log: clean up settled per-path run-log write queue entries so long-running cron uptime does not retain stale promise bookkeeping in memory.</li>
<li>Cron/Isolation: force fresh session IDs for isolated cron runs so <code>sessionTarget="isolated"</code> executions never reuse prior run context. (#23470) Thanks @echoVic.</li>
<li>Plugins/Install: strip <code>workspace:*</code> devDependency entries from copied plugin manifests before <code>npm install --omit=dev</code>, preventing <code>EUNSUPPORTEDPROTOCOL</code> install failures for npm-published channel plugins (including Feishu and MS Teams).</li>
<li>Feishu/Plugins: restore bundled Feishu SDK availability for global installs and strip <code>openclaw: workspace:*</code> from plugin <code>devDependencies</code> during plugin-version sync so npm-installed Feishu plugins do not fail dependency install. (#23611, #23645, #23603)</li>
<li>Config/Channels: auto-enable built-in channels by writing <code>channels.<id>.enabled=true</code> (not <code>plugins.entries.<id></code>), and stop adding built-ins to <code>plugins.allow</code>, preventing <code>plugins.entries.telegram: plugin not found</code> validation failures.</li>
<li>Config/Channels: when <code>plugins.allow</code> is active, auto-enable/enable flows now also allowlist configured built-in channels so <code>channels.<id>.enabled=true</code> cannot remain blocked by restrictive plugin allowlists.</li>
<li>Plugins/Discovery: ignore scanned extension backup/disabled directory patterns (for example <code>.backup-*</code>, <code>.bak</code>, <code>.disabled*</code>) and move updater backup directories under <code>.openclaw-install-backups</code>, preventing duplicate plugin-id collisions from archived copies.</li>
<li>Plugins/CLI: make <code>openclaw plugins enable</code> and plugin install/link flows update allowlists via shared plugin-enable policy so enabled plugins are not left disabled by allowlist mismatch. (#23190) Thanks @downwind7clawd-ctrl.</li>
<li>Security/Voice Call: harden media stream WebSocket handling against pre-auth idle-connection DoS by adding strict pre-start timeouts, pending/per-IP connection limits, and total connection caps for streaming endpoints. This ships in the next npm release. Thanks @jiseoung for reporting.</li>
<li>Security/Sessions: redact sensitive token patterns from <code>sessions_history</code> tool output and surface <code>contentRedacted</code> metadata when masking occurs. (#16928) Thanks @aether-ai-agent.</li>
<li>Security/Exec: stop trusting <code>PATH</code>-derived directories for safe-bin allowlist checks, add explicit <code>tools.exec.safeBinTrustedDirs</code>, and pin safe-bin shell execution to resolved absolute executable paths to prevent binary-shadowing approval bypasses. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Security/Elevated: match <code>tools.elevated.allowFrom</code> against sender identities only (not recipient <code>ctx.To</code>), closing a recipient-token bypass for <code>/elevated</code> authorization. This ships in the next npm release. Thanks @jiseoung for reporting.</li>
<li>Security/Feishu: enforce ID-only allowlist matching for DM/group sender authorization, normalize Feishu ID prefixes during checks, and ignore mutable display names so display-name collisions cannot satisfy allowlist entries. This ships in the next npm release. Thanks @jiseoung for reporting.</li>
<li>Security/Group policy: harden <code>channels.*.groups.*.toolsBySender</code> matching by requiring explicit sender-key types (<code>id:</code>, <code>e164:</code>, <code>username:</code>, <code>name:</code>), preventing cross-identifier collisions across mutable/display-name fields while keeping legacy untyped keys on a deprecated ID-only path. This ships in the next npm release. Thanks @jiseoung for reporting.</li>
<li>Channels/Group policy: fail closed when <code>groupPolicy: "allowlist"</code> is set without explicit <code>groups</code>, honor account-level <code>groupPolicy</code> overrides, and enforce <code>groupPolicy: "disabled"</code> as a hard group block. (#22215) Thanks @etereo.</li>
<li>Telegram/Discord extensions: propagate trusted <code>mediaLocalRoots</code> through extension outbound <code>sendMedia</code> options so extension direct-send media paths honor agent-scoped local-media allowlists. (#20029, #21903, #23227)</li>
<li>Agents/Exec: honor explicit agent context when resolving <code>tools.exec</code> defaults for runs with opaque/non-agent session keys, so per-agent <code>host/security/ask</code> policies are applied consistently. (#11832)</li>
<li>Doctor/Security: add an explicit warning that <code>approvals.exec.enabled=false</code> disables forwarding only, while enforcement remains driven by host-local <code>exec-approvals.json</code> policy. (#15047)</li>
<li>Sandbox/Docker: default sandbox container user to the workspace owner <code>uid:gid</code> when <code>agents.*.sandbox.docker.user</code> is unset, fixing non-root gateway file-tool permissions under capability-dropped containers. (#20979)</li>
<li>Plugins/Media sandbox: propagate trusted <code>mediaLocalRoots</code> through plugin action dispatch (including Discord/Telegram action adapters) so plugin send paths enforce the same agent-scoped local-media sandbox roots as core outbound sends. (#20258, #22718)</li>
<li>Agents/Workspace guard: map sandbox container-workdir file-tool paths (for example <code>/workspace/...</code> and <code>file:///workspace/...</code>) to host workspace roots before workspace-only validation, preventing false <code>Path escapes sandbox root</code> rejections for sandbox file tools. (#9560)</li>
<li>Gateway/Exec approvals: expire approval requests immediately when no approval-capable gateway clients are connected and no forwarding targets are available, avoiding delayed approvals after restarts/offline approver windows. (#22144)</li>
<li>Security/Exec approvals: when approving wrapper commands with allow-always in allowlist mode, persist inner executable paths for known dispatch wrappers (<code>env</code>, <code>nice</code>, <code>nohup</code>, <code>stdbuf</code>, <code>timeout</code>) and fail closed (no persisted entry) when wrapper unwrapping is not safe, preventing wrapper-path approval bypasses. Thanks @tdjackey for reporting.</li>
<li>Node/macOS exec host: default headless macOS node <code>system.run</code> to local execution and only route through the companion app when <code>OPENCLAW_NODE_EXEC_HOST=app</code> is explicitly set, avoiding companion-app filesystem namespace mismatches during exec. (#23547)</li>
<li>Sandbox/Media: map container workspace paths (<code>/workspace/...</code> and <code>file:///workspace/...</code>) back to the host sandbox root for outbound media validation, preventing false deny errors for sandbox-generated local media. (#23083) Thanks @echo931.</li>
<li>Sandbox/Docker: apply custom bind mounts after workspace mounts and prioritize bind-source resolution on overlapping paths, so explicit workspace binds are no longer ignored. (#22669) Thanks @tasaankaeris.</li>
<li>Exec approvals/Forwarding: restore Discord text forwarding when component approvals are not configured, and carry request snapshots through resolve events so resolved notices still forward after cache misses/restarts. (#22988) Thanks @bubmiller.</li>
<li>Control UI/WebSocket: stop and clear the browser gateway client on UI teardown so remounts cannot leave orphan websocket clients that create duplicate active connections. (#23422) Thanks @floatinggball-design.</li>
<li>Control UI/WebSocket: send a stable per-tab <code>instanceId</code> in websocket connect frames so reconnect cycles keep a consistent client identity for diagnostics and presence tracking. (#23616) Thanks @zq58855371-ui.</li>
<li>Config/Memory: allow <code>"mistral"</code> in <code>agents.defaults.memorySearch.provider</code> and <code>agents.defaults.memorySearch.fallback</code> schema validation. (#14934) Thanks @ThomsenDrake.</li>
<li>Feishu/Commands: in group chats, command authorization now falls back to top-level <code>channels.feishu.allowFrom</code> when per-group <code>allowFrom</code> is not set, so <code>/command</code> no longer gets blocked by an unintended empty allowlist. (#23756)</li>
<li>Dev tooling: prevent <code>CLAUDE.md</code> symlink target regressions by excluding CLAUDE symlink sentinels from <code>oxfmt</code> and marking them <code>-text</code> in <code>.gitattributes</code>, so formatter/EOL normalization cannot reintroduce trailing-newline targets. Thanks @vincentkoc.</li>
<li>Agents/Compaction: restore embedded compaction safeguard/context-pruning extension loading in production by wiring bundled extension factories into the resource loader instead of runtime file-path resolution. (#22349) Thanks @Glucksberg.</li>
<li>Agents/Subagents: restore announce-chain delivery to agent injection, defer nested announce output until descendant follow-up content is ready, and prevent descendant deferrals from consuming announce retry budget so deep chains do not drop final completions. (#22223) Thanks @tyler6204.</li>
<li>Agents/System Prompt: label allowlisted senders as authorized senders to avoid implying ownership. Thanks @thewilloftheshadow.</li>
<li>Agents/Tool display: fix exec cwd suffix inference so <code>pushd ... && popd ... && <command></code> does not keep stale <code>(in <dir>)</code> context in summaries. (#21925) Thanks @Lukavyi.</li>
<li>Tools/web_search: handle xAI Responses API payloads that emit top-level <code>output_text</code> blocks (without a <code>message</code> wrapper) so Grok web_search no longer returns <code>No response</code> for those results. (#20508) Thanks @echoVic.</li>
<li>Agents/Failover: treat non-default override runs as direct fallback-to-configured-primary (skip configured fallback chain), normalize default-model detection for provider casing/whitespace, and add regression coverage for override/auth error paths. (#18820) Thanks @Glucksberg.</li>
<li>Docker/Build: include <code>ownerDisplay</code> in <code>CommandsSchema</code> object-level defaults so Docker <code>pnpm build</code> no longer fails with <code>TS2769</code> during plugin SDK d.ts generation. (#22558) Thanks @obviyus.</li>
<li>Docker/Browser: install Playwright Chromium into <code>/home/node/.cache/ms-playwright</code> and set <code>node:node</code> ownership so browser binaries are available to the runtime user in browser-enabled images. (#22585) thanks @obviyus.</li>
<li>Hooks/Session memory: trigger bundled <code>session-memory</code> persistence on both <code>/new</code> and <code>/reset</code> so reset flows no longer skip markdown transcript capture before archival. (#21382) Thanks @mofesolapaul.</li>
<li>Dependencies/Agents: bump embedded Pi SDK packages (<code>@mariozechner/pi-agent-core</code>, <code>@mariozechner/pi-ai</code>, <code>@mariozechner/pi-coding-agent</code>, <code>@mariozechner/pi-tui</code>) to <code>0.54.0</code>. (#21578) Thanks @Takhoffman.</li>
<li>Config/Agents: expose Pi compaction tuning values <code>agents.defaults.compaction.reserveTokens</code> and <code>agents.defaults.compaction.keepRecentTokens</code> in config schema/types and apply them in embedded Pi runner settings overrides with floor enforcement via <code>reserveTokensFloor</code>. (#21568) Thanks @Takhoffman.</li>
<li>Docker: pin base images to SHA256 digests in Docker builds to prevent mutable tag drift. (#7734) Thanks @coygeek.</li>
<li>Docker: run build steps as the <code>node</code> user and use <code>COPY --chown</code> to avoid recursive ownership changes, trimming image size and layer churn. Thanks @huntharo.</li>
<li>Config/Memory: restore schema help/label metadata for hybrid <code>mmr</code> and <code>temporalDecay</code> settings so configuration surfaces show correct names and guidance. (#18786) Thanks @rodrigouroz.</li>
<li>Skills/SonosCLI: add troubleshooting guidance for <code>sonos discover</code> failures on macOS direct mode (<code>sendto: no route to host</code>) and sandbox network restrictions (<code>bind: operation not permitted</code>). (#21316) Thanks @huntharo.</li>
<li>macOS/Build: default release packaging to <code>BUNDLE_ID=ai.openclaw.mac</code> in <code>scripts/package-mac-dist.sh</code>, so Sparkle feed URL is retained and auto-update no longer fails with an empty appcast feed. (#19750) thanks @loganprit.</li>
<li>Signal/Outbound: preserve case for Base64 group IDs during outbound target normalization so cross-context routing and policy checks no longer break when group IDs include uppercase characters. (#5578) Thanks @heyhudson.</li>
<li>Anthropic/Agents: preserve required pi-ai default OAuth beta headers when <code>context1m</code> injects <code>anthropic-beta</code>, preventing 401 auth failures for <code>sk-ant-oat-*</code> tokens. (#19789, fixes #19769) Thanks @minupla.</li>
<li>Security/Exec: block unquoted heredoc body expansion tokens in shell allowlist analysis, reject unterminated heredocs, and require explicit approval for allowlisted heredoc execution on gateway hosts to prevent heredoc substitution allowlist bypass. Thanks @torturado for reporting.</li>
<li>macOS/Security: evaluate <code>system.run</code> allowlists per shell segment in macOS node runtime and companion exec host (including chained shell operators), fail closed on shell/process substitution parsing, and require explicit approval on unsafe parse cases to prevent allowlist bypass via <code>rawCommand</code> chaining. Thanks @tdjackey for reporting.</li>
<li>WhatsApp/Security: enforce allowlist JID authorization for reaction actions so authenticated callers cannot target non-allowlisted chats by forging <code>chatJid</code> + valid <code>messageId</code> pairs. Thanks @aether-ai-agent for reporting.</li>
<li>ACP/Security: escape control and delimiter characters in ACP <code>resource_link</code> title/URI metadata before prompt interpolation to prevent metadata-driven prompt injection through resource links. Thanks @aether-ai-agent for reporting.</li>
<li>TTS/Security: make model-driven provider switching opt-in by default (<code>messages.tts.modelOverrides.allowProvider=false</code> unless explicitly enabled), while keeping voice/style overrides available, to reduce prompt-injection-driven provider hops and unexpected TTS cost escalation. Thanks @aether-ai-agent for reporting.</li>
<li>Security/Agents: keep overflow compaction retry budgeting global across tool-result truncation recovery so successful truncation cannot reset the overflow retry counter and amplify retry/cost cycles. Thanks @aether-ai-agent for reporting.</li>
<li>BlueBubbles/Security: require webhook token authentication for all BlueBubbles webhook requests (including loopback/proxied setups), removing passwordless webhook fallback behavior. Thanks @zpbrent.</li>
<li>iOS/Security: force <code>https://</code> for non-loopback manual gateway hosts during iOS onboarding to block insecure remote transport URLs. (#21969) Thanks @mbelinky.</li>
<li>Gateway/Security: remove shared-IP fallback for canvas endpoints and require token or session capability for canvas access. Thanks @thewilloftheshadow.</li>
<li>Gateway/Security: require secure context and paired-device checks for Control UI auth even when <code>gateway.controlUi.allowInsecureAuth</code> is set, and align audit messaging with the hardened behavior. (#20684) Thanks @coygeek and @Vasco0x4 for reporting.</li>
<li>Gateway/Security: scope tokenless Tailscale forwarded-header auth to Control UI websocket auth only, so HTTP gateway routes still require token/password even on trusted hosts. Thanks @zpbrent for reporting.</li>
<li>Docker/Security: run E2E and install-sh test images as non-root by adding appuser directives. Thanks @thewilloftheshadow.</li>
<li>Skills/Security: sanitize skill env overrides to block unsafe runtime injection variables and only allow sensitive keys when declared in skill metadata, with warnings for suspicious values. Thanks @thewilloftheshadow.</li>
<li>Security/Commands: block prototype-key injection in runtime <code>/debug</code> overrides and require own-property checks for gated command flags (<code>bash</code>, <code>config</code>, <code>debug</code>) so inherited prototype values cannot enable privileged commands. Thanks @tdjackey for reporting.</li>
<li>Security/Browser: block non-network browser navigation protocols (including <code>file:</code>, <code>data:</code>, and <code>javascript:</code>) while preserving <code>about:blank</code>, preventing local file reads via browser tool navigation. Thanks @q1uf3ng for reporting.</li>
<li>Security/Exec: block shell startup-file env injection (<code>BASH_ENV</code>, <code>ENV</code>, <code>BASH_FUNC_*</code>, <code>LD_*</code>, <code>DYLD_*</code>) across config env ingestion, node-host inherited environment sanitization, and macOS exec host runtime to prevent pre-command execution from attacker-controlled environment variables. Thanks @tdjackey.</li>
<li>Security/Exec (Windows): canonicalize <code>cmd.exe /c</code> command text across validation, approval binding, and audit/event rendering to prevent trailing-argument approval mismatches in <code>system.run</code>. Thanks @tdjackey for reporting.</li>
<li>Security/Gateway/Hooks: block <code>__proto__</code>, <code>constructor</code>, and <code>prototype</code> traversal in webhook template path resolution to prevent prototype-chain payload data leakage in <code>messageTemplate</code> rendering. (#22213) Thanks @SleuthCo.</li>
<li>Security/OpenClawKit/UI: prevent injected inbound user context metadata blocks from leaking into chat history in TUI, webchat, and macOS surfaces by stripping all untrusted metadata prefixes at display boundaries. (#22142) Thanks @Mellowambience, @vincentkoc.</li>
<li>Security/OpenClawKit/UI: strip inbound metadata blocks from user messages in TUI rendering while preserving user-authored content. (#22345) Thanks @kansodata, @vincentkoc.</li>
<li>Security/OpenClawKit/UI: prevent inbound metadata leaks and reply-tag streaming artifacts in TUI rendering by stripping untrusted metadata prefixes at display boundaries. (#22346) Thanks @akramcodez, @vincentkoc.</li>
<li>Security/Agents: restrict local MEDIA tool attachments to core tools and the OpenClaw temp root to prevent untrusted MCP tool file exfiltration. Thanks @NucleiAv and @thewilloftheshadow.</li>
<li>Security/Net: strip sensitive headers (<code>Authorization</code>, <code>Proxy-Authorization</code>, <code>Cookie</code>, <code>Cookie2</code>) on cross-origin redirects in <code>fetchWithSsrFGuard</code> to prevent credential forwarding across origin boundaries. (#20313) Thanks @afurm.</li>
<li>Security/Systemd: reject CR/LF in systemd unit environment values and fix argument escaping so generated units cannot be injected with extra directives. Thanks @thewilloftheshadow.</li>
<li>Security/Tools: add per-wrapper random IDs to untrusted-content markers from <code>wrapExternalContent</code>/<code>wrapWebContent</code>, preventing marker spoofing from escaping content boundaries. (#19009) Thanks @Whoaa512.</li>
<li>Shared/Security: reject insecure deep links that use <code>ws://</code> non-loopback gateway URLs to prevent plaintext remote websocket configuration. (#21970) Thanks @mbelinky.</li>
<li>macOS/Security: reject non-loopback <code>ws://</code> remote gateway URLs in macOS remote config to block insecure plaintext websocket endpoints. (#21971) Thanks @mbelinky.</li>
<li>Browser/Security: block upload path symlink escapes so browser upload sources cannot traverse outside the allowed workspace via symlinked paths. (#21972) Thanks @mbelinky.</li>
<li>Security/Dependencies: bump transitive <code>hono</code> usage to <code>4.11.10</code> to incorporate timing-safe authentication comparison hardening for <code>basicAuth</code>/<code>bearerAuth</code> (<code>GHSA-gq3j-xvxp-8hrf</code>). Thanks @vincentkoc.</li>
<li>Security/Gateway: parse <code>X-Forwarded-For</code> with trust-preserving semantics when requests come from configured trusted proxies, preventing proxy-chain spoofing from influencing client IP classification and rate-limit identity. Thanks @AnthonyDiSanti and @vincentkoc.</li>
<li>Security/Sandbox: remove default <code>--no-sandbox</code> for the browser container entrypoint, add explicit opt-in via <code>OPENCLAW_BROWSER_NO_SANDBOX</code> / <code>CLAWDBOT_BROWSER_NO_SANDBOX</code>, and add security-audit checks for stale/missing sandbox browser Docker hash labels. Thanks @TerminalsandCoffee and @vincentkoc.</li>
<li>Security/Sandbox Browser: require VNC password auth for noVNC observer sessions in the sandbox browser entrypoint, plumb per-container noVNC passwords from runtime, and emit short-lived noVNC observer token URLs while keeping loopback-only host port publishing. Thanks @TerminalsandCoffee for reporting.</li>
<li>Security/Sandbox Browser: default browser sandbox containers to a dedicated Docker network (<code>openclaw-sandbox-browser</code>), add optional CDP ingress source-range restrictions, auto-create missing dedicated networks, and warn in <code>openclaw security --audit</code> when browser sandboxing runs on bridge without source-range limits. Thanks @TerminalsandCoffee for reporting.</li>
<li>Feishu/Media: for inbound video messages that include both <code>file_key</code> (video) and <code>image_key</code> (thumbnail), prefer <code>file_key</code> when downloading media so video attachments are saved instead of silently failing on thumbnail keys. (#23633)</li>
<li>Hooks/Loader: avoid redundant hook-module recompilation on gateway restart by skipping cache-busting for bundled hooks and using stable file metadata keys (<code>mtime+size</code>) for mutable workspace/managed/plugin hook imports. (#16953) Thanks @mudrii.</li>
<li>Hooks/Cron: suppress duplicate main-session events for delivered hook turns and mark <code>SILENT_REPLY_TOKEN</code> (<code>NO_REPLY</code>) early exits as delivered to prevent hook context pollution. (#20678) Thanks @JonathanWorks.</li>
<li>Providers/OpenRouter: inject <code>cache_control</code> on system prompts for OpenRouter Anthropic models to improve prompt-cache reuse. (#17473) Thanks @rrenamed.</li>
<li>Installer/Smoke tests: remove legacy <code>OPENCLAW_USE_GUM</code> overrides from docker install-smoke runs so tests exercise installer auto TTY detection behavior directly.</li>
<li>Providers/OpenRouter: allow pass-through OpenRouter and Opencode model IDs in live model filtering so custom routed model IDs are treated as modern refs. (#14312) Thanks @Joly0.</li>
<li>Providers/OpenRouter: default reasoning to enabled when the selected model advertises <code>reasoning: true</code> and no session/directive override is set. (#22513) Thanks @zwffff.</li>
<li>Providers/OpenRouter: map <code>/think</code> levels to <code>reasoning.effort</code> in embedded runs while preserving explicit <code>reasoning.max_tokens</code> payloads. (#17236) Thanks @robbyczgw-cla.</li>
<li>Providers/OpenRouter: preserve stored session provider when model IDs are vendor-prefixed (for example, <code>anthropic/...</code>) so follow-up turns do not incorrectly route to direct provider APIs. (#22753) Thanks @dndodson.</li>
<li>Providers/OpenRouter: preserve the required <code>openrouter/</code> prefix for OpenRouter-native model IDs during model-ref normalization. (#12942) Thanks @omair445.</li>
<li>Providers/OpenRouter: pass through provider routing parameters from model params.provider to OpenRouter request payloads for provider selection controls. (#17148) Thanks @carrotRakko.</li>
<li>Providers/OpenRouter: preserve model allowlist entries containing OpenRouter preset paths (for example <code>openrouter/@preset/...</code>) by treating <code>/model ...@profile</code> auth-profile parsing as a suffix-only override. (#14120) Thanks @NotMainstream.</li>
<li>Cron/Auth: propagate auth-profile resolution to isolated cron sessions so provider API keys are resolved the same way as main sessions, fixing 401 errors when using providers configured via auth-profiles. (#20689) Thanks @lailoo.</li>
<li>Cron/Follow-up: pass resolved <code>agentDir</code> through isolated cron and queued follow-up embedded runs so auth/profile lookups stay scoped to the correct agent directory. (#22845) Thanks @seilk.</li>
<li>Agents/Media: route tool-result <code>MEDIA:</code> extraction through shared parser validation so malformed prose like <code>MEDIA:-prefixed ...</code> is no longer treated as a local file path (prevents Telegram ENOENT tool-error overrides). (#18780) Thanks @HOYALIM.</li>
<li>Logging: cap single log-file size with <code>logging.maxFileBytes</code> (default 500 MB) and suppress additional writes after cap hit to prevent disk exhaustion from repeated error storms.</li>
<li>Memory/Remote HTTP: centralize remote memory HTTP calls behind a shared guarded helper (<code>withRemoteHttpResponse</code>) so embeddings and batch flows use one request/release path.</li>
<li>Memory/Embeddings: apply configured remote-base host pinning (<code>allowedHostnames</code>) across OpenAI/Voyage/Gemini embedding requests to keep private/self-hosted endpoints working without cross-host drift. (#18198) Thanks @ianpcook.</li>
<li>Memory/Batch: route OpenAI/Voyage/Gemini batch upload/create/status/download requests through the same guarded HTTP path for consistent SSRF policy enforcement.</li>
<li>Memory/Index: detect memory source-set changes (for example enabling <code>sessions</code> after an existing memory-only index) and trigger a full reindex so existing session transcripts are indexed without requiring <code>--force</code>. (#17576) Thanks @TarsAI-Agent.</li>
<li>Memory/Embeddings: enforce a per-input 8k safety cap before embedding batching and apply a conservative 2k fallback limit for local providers without declared input limits, preventing oversized session/memory chunks from triggering provider context-size failures during sync/indexing. (#6016) Thanks @batumilove.</li>
<li>Memory/QMD: on Windows, resolve bare <code>qmd</code>/<code>mcporter</code> command names to npm shim executables (<code>.cmd</code>) before spawning, so qmd boot updates and mcporter-backed searches no longer fail with <code>spawn ... ENOENT</code> on default npm installs. (#23899) Thanks @arcbuilder-ai.</li>
<li>Memory/QMD: parse plain-text <code>qmd collection list --json</code> output when older qmd builds ignore JSON mode, and retry memory searches once after re-ensuring managed collections when qmd returns <code>Collection not found ...</code>. (#23613) Thanks @leozhucn.</li>
<li>Signal/RPC: guard malformed Signal RPC JSON responses with a clear status-scoped error and add regression coverage for invalid JSON responses. (#22995) Thanks @adhitShet.</li>
<li>Gateway/Subagents: guard gateway and subagent session-key/message trim paths against undefined inputs to prevent early <code>Cannot read properties of undefined (reading 'trim')</code> crashes during subagent spawn and wait flows.</li>
<li>Agents/Workspace: guard <code>resolveUserPath</code> against undefined/null input to prevent <code>Cannot read properties of undefined (reading 'trim')</code> crashes when workspace paths are missing in embedded runner flows.</li>
<li>Auth/Profiles: keep active <code>cooldownUntil</code>/<code>disabledUntil</code> 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 <code>usageStats</code> cleanup. (#23516, #23536) Thanks @arosstale.</li>
<li>Channels/Security: fail closed on missing provider group policy config by defaulting runtime group policy to <code>allowlist</code> (instead of inheriting <code>channels.defaults.groupPolicy</code>) when <code>channels.<provider></code> 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.</li>
<li>Gateway/Onboarding: harden remote gateway onboarding defaults and guidance by defaulting discovered direct URLs to <code>wss://</code>, rejecting insecure non-loopback <code>ws://</code> targets in onboarding validation, and expanding remote-security remediation messaging across gateway client/call/doctor flows. (#23476) Thanks @bmendonca3.</li>
<li>CLI/Sessions: pass the configured sessions directory when resolving transcript paths in <code>agentCommand</code>, so custom <code>session.store</code> locations resume sessions reliably. Thanks @davidrudduck.</li>
<li>Signal/Monitor: treat user-initiated abort shutdowns as clean exits when auto-started <code>signal-cli</code> is terminated, while still surfacing unexpected daemon exits as startup/runtime failures. (#23379) Thanks @frankekn.</li>
<li>Channels/Dedupe: centralize plugin dedupe primitives in plugin SDK (memory + persistent), move Feishu inbound dedupe to a namespace-scoped persistent store, and reuse shared dedupe cache logic for Zalo webhook replay + Tlon processed-message tracking to reduce duplicate handling during reconnect/replay paths. (#23377) Thanks @SidQin-cyber.</li>
<li>Channels/Delivery: remove hardcoded WhatsApp delivery fallbacks; require explicit/session channel context or auto-pick the sole configured channel when unambiguous. (#23357) Thanks @lbo728.</li>
<li>ACP/Gateway: wait for gateway hello before opening ACP requests, and fail fast on pre-hello connect failures to avoid startup hangs and early <code>gateway not connected</code> request races. (#23390) Thanks @janckerchen.</li>
<li>Gateway/Auth: preserve <code>OPENCLAW_GATEWAY_PASSWORD</code> env override precedence for remote gateway call credentials after shared resolver refactors, preventing stale configured remote passwords from overriding runtime secret rotation.</li>
<li>Gateway/Auth: preserve shared-token <code>gateway token mismatch</code> auth errors when <code>auth.token</code> fallback device-token checks fail, and reserve <code>device token mismatch</code> guidance for explicit <code>auth.deviceToken</code> failures.</li>
<li>Gateway/Tools: when agent tools pass an allowlisted <code>gatewayUrl</code> override, resolve local override tokens from env/config fallback but keep remote overrides strict to <code>gateway.remote.token</code>, preventing local token leakage to remote targets.</li>
<li>Gateway/Client: keep cached device-auth tokens on <code>device token mismatch</code> closes when the client used explicit shared token/password credentials, avoiding accidental pairing-token churn during explicit-auth failures.</li>
<li>Node host/Exec: keep strict Windows allowlist behavior for <code>cmd.exe /c</code> shell-wrapper runs, and return explicit approval guidance when blocked (<code>SYSTEM_RUN_DENIED: allowlist miss</code>).</li>
<li>Control UI: show pairing-required guidance (commands + mobile tokenized URL reminder) when the dashboard disconnects with <code>1008 pairing required</code>.</li>
<li>Security/Audit: add <code>openclaw security audit</code> detection for open group policies that expose runtime/filesystem tools without sandbox/workspace guards (<code>security.exposure.open_groups_with_runtime_or_fs</code>).</li>
<li>Security/Audit: make <code>gateway.real_ip_fallback_enabled</code> severity conditional for loopback trusted-proxy setups (warn for loopback-only <code>trustedProxies</code>, critical when non-loopback proxies are trusted). (#23428) Thanks @bmendonca3.</li>
<li>Security/Exec env: block request-scoped <code>HOME</code> and <code>ZDOTDIR</code> overrides in host exec env sanitizers (Node + macOS), preventing shell startup-file execution before allowlist-evaluated command bodies. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Security/Exec env: block <code>SHELLOPTS</code>/<code>PS4</code> in host exec env sanitizers and restrict shell-wrapper (<code>bash|sh|zsh ... -c/-lc</code>) request env overrides to a small explicit allowlist (<code>TERM</code>, <code>LANG</code>, <code>LC_*</code>, <code>COLORTERM</code>, <code>NO_COLOR</code>, <code>FORCE_COLOR</code>) on both node host and macOS companion paths, preventing xtrace prompt command-substitution allowlist bypasses. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>WhatsApp/Security: enforce <code>allowFrom</code> for direct-message outbound targets in all send modes (including <code>mode: "explicit"</code>), preventing sends to non-allowlisted numbers. (#20108) Thanks @zahlmann.</li>
<li>Security/Exec approvals: fail closed on shell line continuations (<code>\\\n</code>/<code>\\\r\n</code>) and treat shell-wrapper execution as approval-required in allowlist mode, preventing <code>$\\</code> newline command-substitution bypasses. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Security/Gateway: emit a startup security warning when insecure/dangerous config flags are enabled (including <code>gateway.controlUi.dangerouslyDisableDeviceAuth=true</code>) and point operators to <code>openclaw security audit</code>.</li>
<li>Security/Hooks auth: normalize hook auth rate-limit client IP keys so IPv4 and IPv4-mapped IPv6 addresses share one throttle bucket, preventing dual-form auth-attempt budget bypasses. This ships in the next npm release. Thanks @aether-ai-agent for reporting.</li>
<li>Security/Exec approvals: treat <code>env</code> and shell-dispatch wrappers as transparent during allowlist analysis on node-host and macOS companion paths so policy checks match the effective executable/inline shell payload instead of the wrapper binary, blocking wrapper-smuggled allowlist bypasses. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Security/Exec approvals: require explicit safe-bin profiles for <code>tools.exec.safeBins</code> entries in allowlist mode (remove generic safe-bin profile fallback), and add <code>tools.exec.safeBinProfiles</code> for safe custom binaries so unprofiled interpreter-style entries cannot be treated as stdin-safe. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Security/Channels: harden Slack external menu token handling by switching to CSPRNG tokens, validating token shape, requiring user identity for external option lookups, and avoiding fabricated timestamp <code>trigger_id</code> fallbacks; also switch Tlon Urbit channel IDs to CSPRNG UUIDs, centralize secure ID/token generation via shared infra helpers, and add a guardrail test to block new runtime <code>Date.now()+Math.random()</code> token/id patterns.</li>
<li>Security/Hooks transforms: enforce symlink-safe containment for webhook transform module paths (including <code>hooks.transformsDir</code> and <code>hooks.mappings[].transform.module</code>) by resolving existing-path ancestors via realpath before import, while preserving in-root symlink support; add regression coverage for both escape and allow cases. This ships in the next npm release. Thanks @aether-ai-agent for reporting.</li>
<li>Telegram/WSL2: disable <code>autoSelectFamily</code> by default on WSL2 and memoize WSL2 detection in Telegram network decision logic to avoid repeated sync <code>/proc/version</code> probes on fetch/send paths. (#21916) Thanks @MizukiMachine.</li>
<li>Telegram/Network: default Node 22+ DNS result ordering to <code>ipv4first</code> for Telegram fetch paths and add <code>OPENCLAW_TELEGRAM_DNS_RESULT_ORDER</code>/<code>channels.telegram.network.dnsResultOrder</code> overrides to reduce IPv6-path fetch failures. (#5405) Thanks @Glucksberg.</li>
<li>Telegram/Forward bursts: coalesce forwarded text+media updates through a dedicated forward lane debounce window that works with default inbound debounce config, while keeping forwarded control commands immediate. (#19476) thanks @napetrov.</li>
<li>Telegram/Streaming: preserve archived draft preview mapping after flush and clean superseded reasoning preview bubbles so multi-message preview finals no longer cross-edit or orphan stale messages under send/rotation races. (#23202) Thanks @obviyus.</li>
<li>Telegram/Replies: scope messaging-tool text/media dedupe to same-target sends only, so cross-target tool sends can no longer silently suppress Telegram final replies.</li>
<li>Telegram/Replies: normalize <code>file://</code> and local-path media variants during messaging dedupe so equivalent media paths do not produce duplicate Telegram replies.</li>
<li>Telegram/Replies: extract forwarded-origin context from unified reply targets (<code>reply_to_message</code> and <code>external_reply</code>) so forward+comment metadata is preserved across partial reply shapes. (#9720) thanks @mcaxtr.</li>
<li>Telegram/Polling: persist a safe update-offset watermark bounded by pending updates so crash/restart cannot skip queued lower <code>update_id</code> updates after out-of-order completion. (#23284) thanks @frankekn.</li>
<li>Telegram/Polling: force-restart stuck runner instances when recoverable unhandled network rejections escape the polling task path, so polling resumes instead of silently stalling. (#19721) Thanks @jg-noncelogic.</li>
<li>Slack/Slash commands: preserve the Bolt app receiver when registering external select options handlers so monitor startup does not crash on runtimes that require bound <code>app.options</code> calls. (#23209) Thanks @0xgaia.</li>
<li>Slack/Telegram slash sessions: await session metadata persistence before dispatch so first-turn native slash runs do not race session-origin metadata updates. (#23065) thanks @hydro13.</li>
<li>Slack/Queue routing: preserve string <code>thread_ts</code> values through collect-mode queue drain and DM <code>deliveryContext</code> updates so threaded follow-ups do not leak to the main channel when Slack thread IDs are strings. (#11934) Thanks @sandieman2 and @vincentkoc.</li>
<li>Telegram/Native commands: set <code>ctx.Provider="telegram"</code> for native slash-command context so elevated gate checks resolve provider correctly (fixes <code>provider (ctx.Provider)</code> failures in <code>/elevated</code> flows). (#23748) Thanks @serhii12.</li>
<li>Agents/Ollama: preserve unsafe integer tool-call arguments as exact strings during NDJSON parsing, preventing large numeric IDs from being rounded before tool execution. (#23170) Thanks @BestJoester.</li>
<li>Cron/Gateway: keep <code>cron.list</code> and <code>cron.status</code> responsive during startup catch-up by avoiding a long-held cron lock while missed jobs execute. (#23106) Thanks @jayleekr.</li>
<li>Gateway/Config reload: compare array-valued config paths structurally during diffing so unchanged <code>memory.qmd.paths</code> and <code>memory.qmd.scope.rules</code> no longer trigger false restart-required reloads. (#23185) Thanks @rex05ai.</li>
<li>Gateway/Config reload: retry short-lived missing config snapshots during reload before skipping, preventing atomic-write unlink windows from triggering restart loops. (#23343) Thanks @lbo728.</li>
<li>Cron/Scheduling: validate runtime cron expressions before schedule/stagger evaluation so malformed persisted jobs report a clear <code>invalid cron schedule: expr is required</code> error instead of crashing with <code>undefined.trim</code> failures and auto-disable churn. (#23223) Thanks @asimons81.</li>
<li>Memory/QMD: migrate legacy unscoped collection bindings (for example <code>memory-root</code>) to per-agent scoped names (for example <code>memory-root-main</code>) during startup when safe, so QMD-backed <code>memory_search</code> no longer fails with <code>Collection not found</code> after upgrades. (#23228, #20727) Thanks @JLDynamics and @AaronFaby.</li>
<li>Memory/QMD: normalize Han-script BM25 search queries before invoking <code>qmd search</code> so mixed CJK+Latin prompts no longer return empty results due to tokenizer mismatch. (#23426) Thanks @LunaLee0130.</li>
<li>TUI/Input: enable multiline-paste burst coalescing on macOS Terminal.app and iTerm so pasted blocks no longer submit line-by-line as separate messages. (#18809) Thanks @fwends.</li>
<li>TUI/RTL: isolate right-to-left script lines (Arabic/Hebrew ranges) with Unicode bidi isolation marks in TUI text sanitization so RTL assistant output no longer renders in reversed visual order in terminal chat panes. (#21936) Thanks @Asm3r96.</li>
<li>TUI/Status: request immediate renders after setting <code>sending</code>/<code>waiting</code> activity states so in-flight runs always show visible progress indicators instead of appearing idle until completion. (#21549) Thanks @13Guinness.</li>
<li>TUI/Input: arm Ctrl+C exit timing when clearing non-empty composer text and add a SIGINT fallback path so double Ctrl+C exits remain responsive during active runs instead of requiring an extra press or appearing stuck. (#23407) Thanks @tinybluedev.</li>
<li>Agents/Fallbacks: treat JSON payloads with <code>type: "api_error"</code> + <code>"Internal server error"</code> as transient failover errors so Anthropic 500-style failures trigger model fallback. (#23193) Thanks @jarvis-lane.</li>
<li>Agents/Google: sanitize non-base64 <code>thought_signature</code>/<code>thoughtSignature</code> values from assistant replay transcripts for native Google Gemini requests while preserving valid signatures and tool-call order. (#23457) Thanks @echoVic.</li>
<li>Agents/Transcripts: validate assistant tool-call names (syntax/length + registered tool allowlist) before transcript persistence and during replay sanitization so malformed failover tool names no longer poison sessions with repeated provider HTTP 400 errors. (#23324) Thanks @johnsantry.</li>
<li>Agents/Mistral: sanitize tool-call IDs in the embedded agent loop and generate strict provider-safe pending tool-call IDs, preventing Mistral strict9 <code>HTTP 400</code> failures on tool continuations. (#23698) Thanks @echoVic.</li>
<li>Agents/Compaction: strip stale assistant usage snapshots from pre-compaction turns when replaying history after a compaction summary so context-token estimation no longer reuses pre-compaction totals and immediately re-triggers destructive follow-up compactions. (#19127) Thanks @tedwatson.</li>
<li>Agents/Replies: emit a default completion acknowledgement (<code>✅ Done.</code>) only for direct/private tool-only completions with no final assistant text, while suppressing synthetic acknowledgements for channel/group sessions and runs that already delivered output via messaging tools. (#22834) Thanks @Oldshue.</li>
<li>Agents/Subagents: honor <code>tools.subagents.tools.alsoAllow</code> and explicit subagent <code>allow</code> entries when resolving built-in subagent deny defaults, so explicitly granted tools (for example <code>sessions_send</code>) are no longer blocked unless re-denied in <code>tools.subagents.tools.deny</code>. (#23359) Thanks @goren-beehero.</li>
<li>Agents/Subagents: make announce call timeouts configurable via <code>agents.defaults.subagents.announceTimeoutMs</code> and restore a 60s default to prevent false timeout failures on slower announce paths. (#22719) Thanks @Valadon.</li>
<li>Agents/Diagnostics: include resolved lifecycle error text in <code>embedded run agent end</code> warnings so UI/TUI “Connection error” runs expose actionable provider failure reasons in gateway logs. (#23054) Thanks @Raize.</li>
<li>Agents/Auth profiles: skip auth-profile cooldown writes for timeout failures in embedded runner rotation so model/network timeouts do not poison same-provider fallback model selection while still allowing in-turn account rotation. (#22622) Thanks @vageeshkumar.</li>
<li>Plugins/Hooks: run legacy <code>before_agent_start</code> once per agent turn and reuse that result across model-resolve and prompt-build compatibility paths, preventing duplicate hook side effects (for example duplicate external API calls). (#23289) Thanks @ksato8710.</li>
<li>Models/Config: default missing Anthropic provider/model <code>api</code> fields to <code>anthropic-messages</code> during config validation so custom relay model entries are preserved instead of being dropped by runtime model registry validation. (#23332) Thanks @bigbigmonkey123.</li>
<li>Gateway/Pairing: preserve existing approved token scopes when processing repair pairings that omit <code>scopes</code>, preventing empty-scope token regressions on reconnecting clients. (#21906) Thanks @paki81.</li>
<li>Memory/QMD: add optional <code>memory.qmd.mcporter</code> search routing so QMD <code>query/search/vsearch</code> can run through mcporter keep-alive flows (including multi-collection paths) to reduce cold starts, while keeping searches on agent-scoped QMD state for consistent recall. (#19617) Thanks @nicole-luxe and @vignesh07.</li>
<li>Infra/Network: classify undici <code>TypeError: fetch failed</code> as transient in unhandled-rejection detection even when nested causes are unclassified, preventing avoidable gateway crash loops on flaky networks. (#14345) Thanks @Unayung.</li>
<li>Telegram/Retry: classify undici <code>TypeError: fetch failed</code> as recoverable in both polling and send retry paths so transient fetch failures no longer fail fast. (#16699) thanks @Glucksberg.</li>
<li>Docs/Telegram: correct Node 22+ network defaults (<code>autoSelectFamily</code>, <code>dnsResultOrder</code>) and clarify Telegram setup does not use positional <code>openclaw channels login telegram</code>. (#23609) Thanks @ryanbastic.</li>
<li>BlueBubbles/DM history: restore DM backfill context with account-scoped rolling history, bounded backfill retries, and safer history payload limits. (#20302) Thanks @Ryan-Haines.</li>
<li>BlueBubbles/Private API cache: treat unknown (<code>null</code>) private-API cache status as disabled for send/attachment/reply flows to avoid stale-cache 500s, and log a warning when reply/effect features are requested while capability is unknown. (#23459) Thanks @echoVic.</li>
<li>BlueBubbles/Webhooks: accept inbound/reaction webhook payloads when BlueBubbles omits <code>handle</code> but provides DM <code>chatGuid</code>, and harden payload extraction for array/string-wrapped message bodies so valid webhook events no longer get rejected as unparseable. (#23275) Thanks @toph31.</li>
<li>Security/Audit: add <code>openclaw security audit</code> finding <code>gateway.nodes.allow_commands_dangerous</code> for risky <code>gateway.nodes.allowCommands</code> overrides, with severity upgraded to critical on remote gateway exposure.</li>
<li>Gateway/Control plane: reduce cross-client write limiter contention by adding <code>connId</code> fallback keying when device ID and client IP are both unavailable.</li>
<li>Security/Config: block prototype-key traversal during config merge patch and legacy migration merge helpers (<code>__proto__</code>, <code>constructor</code>, <code>prototype</code>) to prevent prototype pollution during config mutation flows. (#22968) Thanks @Clawborn.</li>
<li>Security/Shell env: validate login-shell executable paths for shell-env fallback (<code>/etc/shells</code> + trusted prefixes), block <code>SHELL</code>/<code>HOME</code>/<code>ZDOTDIR</code> in config env ingestion before fallback execution, and sanitize fallback shell exec env to pin <code>HOME</code> to the real user home while dropping <code>ZDOTDIR</code> and other dangerous startup vars. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Network/SSRF: enable <code>autoSelectFamily</code> on pinned undici dispatchers (with attempt timeout) so IPv6-unreachable environments can quickly fall back to IPv4 for guarded fetch paths. (#19950) Thanks @ENAwareness.</li>
<li>Security/Config: make parsed chat allowlist checks fail closed when <code>allowFrom</code> is empty, restoring expected DM/pairing gating.</li>
<li>Security/Exec: in non-default setups that manually add <code>sort</code> to <code>tools.exec.safeBins</code>, block <code>sort --compress-program</code> so allowlist-mode safe-bin checks cannot bypass approval. Thanks @tdjackey for reporting.</li>
<li>Security/Exec approvals: when users choose <code>allow-always</code> for shell-wrapper commands (for example <code>/bin/zsh -lc ...</code>), persist allowlist patterns for the inner executable(s) instead of the wrapper shell binary, preventing accidental broad shell allowlisting in moderate mode. (#23276) Thanks @xrom2863.</li>
<li>Security/Exec: fail closed when <code>tools.exec.host=sandbox</code> is configured/requested but sandbox runtime is unavailable. (#23398) Thanks @bmendonca3.</li>
<li>Security/macOS app beta: enforce path-only <code>system.run</code> allowlist matching (drop basename matches like <code>echo</code>), migrate legacy basename entries to last resolved paths when available, and harden shell-chain handling to fail closed on unsafe parse/control syntax (including quoted command substitution/backticks). This is an optional allowlist-mode feature; default installs remain deny-by-default. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Security/Agents: auto-generate and persist a dedicated <code>commands.ownerDisplaySecret</code> when <code>commands.ownerDisplay=hash</code>, remove gateway token fallback from owner-ID prompt hashing across CLI and embedded agent runners, and centralize owner-display secret resolution in one shared helper. This ships in the next npm release. Thanks @aether-ai-agent for reporting.</li>
<li>Security/SSRF: expand IPv4 fetch guard blocking to include RFC special-use/non-global ranges (including benchmarking, TEST-NET, multicast, and reserved/broadcast blocks), centralize range checks into a single CIDR policy table, and reuse one shared host/IP classifier across literal + DNS checks to reduce classifier drift. This ships in the next npm release. Thanks @princeeismond-dot for reporting.</li>
<li>Security/SSRF: block RFC2544 benchmarking range (<code>198.18.0.0/15</code>) across direct and embedded-IP paths, and normalize IPv6 dotted-quad transition literals (for example <code>::127.0.0.1</code>, <code>64:ff9b::8.8.8.8</code>) in shared IP parsing/classification.</li>
<li>Security/Archive: block zip symlink escapes during archive extraction.</li>
<li>Security/Media sandbox: keep tmp media allowance for absolute tmp paths only and enforce symlink-escape checks before sandbox-validated reads, preventing tmp symlink exfiltration and relative <code>../</code> sandbox escapes when sandboxes live under tmp. (#17892) Thanks @dashed.</li>
<li>Browser/Upload: accept canonical in-root upload paths when the configured uploads directory is a symlink alias (for example <code>/tmp</code> -> <code>/private/tmp</code> on macOS), so browser upload validation no longer rejects valid files during client->server revalidation. (#23300, #23222, #22848) Thanks @bgaither4, @parkerati, and @Nabsku.</li>
<li>Security/Discord: add <code>openclaw security audit</code> warnings for name/tag-based Discord allowlist entries (DM allowlists, guild/channel <code>users</code>, and pairing-store entries), highlighting slug-collision risk while keeping name-based matching supported, and canonicalize resolved Discord allowlist names to IDs at runtime without rewriting config files. Thanks @tdjackey for reporting.</li>
<li>Security/Gateway: block node-role connections when device identity metadata is missing.</li>
<li>Security/Media: enforce inbound media byte limits during download/read across Discord, Telegram, Zalo, Microsoft Teams, and BlueBubbles to prevent oversized payload memory spikes before rejection. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Media/Understanding: preserve <code>application/pdf</code> MIME classification during text-like file heuristics so PDF uploads use PDF extraction paths instead of being inlined as raw text. (#23191) Thanks @claudeplay2026-byte.</li>
<li>Security/Control UI: block symlink-based out-of-root static file reads by enforcing realpath containment and file-identity checks when serving Control UI assets and SPA fallback <code>index.html</code>. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Security/Gateway avatars: block symlink traversal during local avatar <code>data:</code> URL resolution by enforcing realpath containment and file-identity checks before reads. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Security/Control UI: centralize avatar URL/path validation across gateway/config helpers and enforce a 2 MB max size for local agent avatar files before <code>/avatar</code> resolution, reducing oversized-avatar memory risk without changing supported avatar formats.</li>
<li>Security/Control UI avatars: harden <code>/avatar/:agentId</code> local avatar serving by rejecting symlink paths and requiring fd-level file identity + size checks before reads. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Security/MSTeams media: enforce allowlist checks for SharePoint reference attachment URLs and redirect targets during Graph-backed media fetches so redirect chains cannot escape configured media host boundaries. This ships in the next npm release. Thanks @tdjackey for reporting.</li>
<li>Security/MSTeams media: route attachment auth-retry and Graph SharePoint download redirects through shared <code>safeFetch</code> so each hop is validated with allowlist + DNS/IP checks across the full redirect chain. (#23598) Thanks @Asm3r96 and @lewiswigmore.</li>
<li>Security/macOS discovery: fail closed for unresolved discovery endpoints by clearing stale remote selection values, use resolved service host only for SSH target derivation, and keep remote URL config aligned with resolved endpoint availability. (#21618) Thanks @bmendonca3.</li>
<li>Chat/Usage/TUI: strip synthetic inbound metadata blocks (including <code>Conversation info</code> and trailing <code>Untrusted context</code> channel metadata wrappers) from displayed conversation history so internal prompt context no longer leaks into user-visible logs.</li>
<li>CI/Tests: fix TypeScript case-table typing and lint assertion regressions so <code>pnpm check</code> passes again after Synology Chat landing. (#23012) Thanks @druide67.</li>
<li>Security/Browser relay: harden extension relay auth token handling for <code>/extension</code> and <code>/cdp</code> pathways.</li>
<li>Cron: persist <code>delivered</code> state in cron job records so delivery failures remain visible in status and logs. (#19174) Thanks @simonemacario.</li>
<li>Config/Doctor: only repair the OAuth credentials directory when affected channels are configured, avoiding fresh-install noise.</li>
<li>Config/Channels: whitelist <code>channels.modelByChannel</code> in config validation and exclude it from plugin auto-enable channel detection so model overrides no longer trigger <code>unknown channel id</code> validation errors or bogus <code>modelByChannel</code> plugin enables. (#23412) Thanks @ProspectOre.</li>
<li>Config/Bindings: allow optional <code>bindings[].comment</code> in strict config validation so annotated binding entries no longer fail load. (#23458) Thanks @echoVic.</li>
<li>Usage/Pricing: correct MiniMax M2.5 pricing defaults to fix inflated cost reporting. (#22755) Thanks @miloudbelarebia.</li>
<li>Gateway/Daemon: verify gateway health after daemon restart.</li>
<li>Agents/UI text: stop rewriting normal assistant billing/payment language outside explicit error contexts. (#17834) Thanks @niceysam.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.2.21/OpenClaw-2026.2.21.zip" length="23065599" type="application/octet-stream" sparkle:edSignature="Wg3P8rMvYO3uWoVR7Izxjm5hC5W0C5jCG2dR4WFSe8ULpUUU79YDJc99NMBnl8ym7ZVbelS3kZ0QSg0Wq2GhCw=="/>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.2.22-beta.1/OpenClaw-2026.2.22.zip" length="23096856" type="application/octet-stream" sparkle:edSignature="aoVaCQPj9ajiSD+OjMZdUOyNzACFlMxU7m4ns+4LF1eWaizGLGHk4S0OPnHVQ+DAQY2DCHua+z4F0SMI6o01DA=="/>
</item>
</channel>
</rss>