Changes
- Auto-reply/Abort shortcuts: expand standalone stop phrases (
stop openclaw,stop action,stop run,stop agent,please stop, and related variants), accept trailing punctuation (for exampleSTOP OPENCLAW!!!), add multilingual stop keywords (including ES/FR/ZH/HI/AR/JP/DE/PT/RU forms), and treat exactdo not do thatas a stop trigger while preserving strict standalone matching. (#25103) Thanks @steipete and @vincentkoc. - Android/App UX: ship a native four-step onboarding flow, move post-onboarding into a five-tab shell (Connect, Chat, Voice, Screen, Settings), add a full Connect setup/manual mode screen, and refresh Android chat/settings surfaces for the new navigation model.
- Talk/Gateway config: add provider-agnostic Talk configuration with legacy compatibility, and expose gateway Talk ElevenLabs config metadata for setup/status surfaces.
- Security/Audit: add
security.trust_model.multi_user_heuristicto flag likely shared-user ingress and clarify the personal-assistant trust model, with hardening guidance for intentional multi-user setups (sandbox.mode="all", workspace-scoped FS, reduced tool surface, no personal/private identities on shared runtimes). - Dependencies: refresh key runtime and tooling packages across the workspace (Bedrock SDK, pi runtime stack, OpenAI, Google auth, and oxlint/oxfmt), while intentionally keeping
@buape/carbonpinned.
Fixes
- Routing/Session isolation: harden followup routing so explicit cross-channel origin replies never fall back to the active dispatcher on route failure, preserve queued overflow summary routing metadata (
channel/to/thread) across followup drain, and prefer originating channel context over internal provider tags for embedded followup runs. This prevents webchat/control-ui context from hijacking Discord-targeted replies in shared sessions. (#25864) Thanks @Gamedesigner. - Security/Routing: fail closed for shared-session cross-channel replies by binding outbound target resolution to the current turn’s source channel metadata (instead of stale session route fallbacks), and wire those turn-source fields through gateway + command delivery planners with regression coverage. (#24571) Thanks @brandonwise.
- Heartbeat routing: prevent heartbeat leakage/spam into Discord and other direct-message destinations by blocking direct-chat heartbeat delivery targets and keeping blocked-delivery cron/exec prompts internal-only. (#25871)
- Heartbeat defaults/prompts: switch the implicit heartbeat delivery target from
lasttonone(opt-in for external delivery), and use internal-only cron/exec heartbeat prompt wording when delivery is disabled so background checks do not nudge user-facing relay behavior. (#25871, #24638, #25851) - Auto-reply/Heartbeat queueing: drop heartbeat runs when a session already has an active run instead of enqueueing a stale followup, preventing duplicate heartbeat response branches after queue drain. (#25610, #25606) Thanks @mcaxtr.
- Cron/Heartbeat delivery: stop inheriting cached session
lastThreadIdfor heartbeat-mode target resolution unless a thread/topic is explicitly requested, so announce-mode cron and heartbeat deliveries stay on top-level destinations instead of leaking into active conversation threads. (#25730) Thanks @markshields-tl. - Messaging tool dedupe: treat originating channel metadata as authoritative for same-target
message.sendsuppression in proactive runs (heartbeat/cron/exec-event), including synthetic-provider contexts, sodelivery-mirrortranscript entries no longer cause duplicate Telegram sends. (#25835) Thanks @jadeathena84-arch. - Channels/Typing keepalive: refresh channel typing callbacks on a keepalive interval during long replies and clear keepalive timers on idle/cleanup across core + extension dispatcher callsites so typing indicators do not expire mid-inference. (#25886, #25882) Thanks @stakeswky.
- Agents/Model fallback: when a run is currently on a configured fallback model, keep traversing the configured fallback chain instead of collapsing straight to primary-only, preventing dead-end failures when primary stays in cooldown. (#25922, #25912) Thanks @Taskle.
- Gateway/Models: honor explicit
agents.defaults.modelsallowlist refs even when bundled model catalog data is stale, synthesize missing allowlist entries inmodels.list, and allowsessions.patch//modelselection for those refs without falsemodel not allowederrors. (#20291) Thanks @kensipe, @nikolasdehor, and @vincentkoc. - Control UI/Agents: inherit
agents.defaults.model.fallbacksin the Overview fallback input when no per-agent model entry exists, while preserving explicit per-agent fallback overrides (including empty lists). (#25729, #25710) Thanks @Suko. - Automation/Subagent/Cron reliability: honor
ANNOUNCE_SKIPinsessions_spawncompletion/direct announce flows (no user-visible token leaks), add transient direct-announce retries for channel unavailability (for example WhatsApp listener reconnect windows), and includecronin thecodingtool profile so/tools/invokecan execute cron actions when explicitly allowed by gateway policy. (#25800, #25656, #25842, #25813, #25822, #25821) Thanks @astra-fer, @aaajiao, @dwight11232-coder, @kevinWangSheng, @widingmarcus-cyber, and @stakeswky. - Discord/Voice reliability: restore runtime DAVE dependency (
@snazzah/davey), add configurable DAVE join options (channels.discord.voice.daveEncryptionandchannels.discord.voice.decryptionFailureTolerance), clean up voice listeners/session teardown, guard against stale connection events, and trigger controlled rejoin recovery after repeated decrypt failures to improve inbound STT stability under DAVE receive errors. (#25861, #25372, #24883, #24825, #23890, #23105, #22961, #23421, #23278, #23032) - Discord/Block streaming: restore block-streamed reply delivery by suppressing only reasoning payloads (instead of all
blockpayloads), fixing missing Discord replies inchannels.discord.streaming=blockmode. (#25839, #25836, #25792) Thanks @pewallin. - Discord/Proxy + reactions + model picker: thread channel proxy fetch into inbound media/sticker downloads, use proxy-aware gateway metadata fetch for WSL/corporate proxy setups, wire
messages.statusReactions.{emojis,timing}into Discord reaction lifecycle control, and compact model-pickercustom_idkeys to stay under Discord's 100-char limit while keeping backward-compatible parsing. (#25232, #25507, #25564, #25695) Thanks @openperf, @chilu18, @Yipsh, @lbo728, and @s1korrrr. - WhatsApp/Web reconnect: treat close status
440as non-retryable (including string-form status values), stop reconnect loops immediately, and emit operator guidance to relink after resolving session conflicts. (#25858) Thanks @markmusson. - WhatsApp/Reasoning safety: suppress outbound payloads marked as reasoning and hard-drop text payloads that begin with
Reasoning:before WhatsApp delivery, preventing hidden thinking blocks from leaking to end users through final-message paths. (#25804, #25214, #24328) - Matrix/Read receipts: send read receipts as soon as Matrix messages arrive (before handler pipeline work), so clients no longer show long-lived unread/sent states while replies are processing. (#25841, #25840) Thanks @joshjhall.
- Telegram/Replies: when markdown formatting renders to empty HTML (for example syntax-only chunks in threaded replies), retry delivery with plain text, and fail loud when both formatted and plain payloads are empty to avoid false delivered states. (#25096, #25091) Thanks @Glucksberg.
- Telegram/Media fetch: prioritize IPv4 before IPv6 in SSRF pinned DNS address ordering so media downloads still work on hosts with broken IPv6 routing. (#24295, #23975) Thanks @Glucksberg.
- Telegram/Outbound API: replace Node 22's global undici dispatcher when applying Telegram
autoSelectFamilydecisions so outboundfetchcalls inherit IPv4 fallback instead of staying pinned to stale dispatcher settings. (#25682, #25676) Thanks @lairtonlelis. - Onboarding/Telegram: keep core-channel onboarding available when plugin registry population is missing by falling back to built-in adapters and continuing wizard setup with actionable recovery guidance. (#25803) Thanks @Suko.
- Android/Gateway auth: preserve Android gateway auth state across onboarding, use the native client id for operator sessions, retry with shared-token fallback after device-token auth failures, and avoid clearing tokens on transient connect errors.
- Slack/DM routing: treat
D*channel IDs as direct messages even when Slack sends an incorrectchannel_type, preventing DM traffic from being misclassified as channel/group chats. (#25479) Thanks @mcaxtr. - Zalo/Group policy: enforce sender authorization for group messages with
groupPolicy+groupAllowFrom(fallback toallowFrom), default runtime group behavior to fail-closed allowlist, and block unauthorized non-command group messages before dispatch. Thanks @tdjackey for reporting. - macOS/Voice input: guard all audio-input startup paths against missing default microphones (Voice Wake, Talk Mode, Push-to-Talk, mic-level monitor, tester) to avoid launch/runtime crashes on mic-less Macs and fail gracefully until input becomes available. (#25817) Thanks @sfo2001.
- macOS/IME input: when marked text is active, treat Return as IME candidate confirmation first in both the voice overlay composer and shared chat composer to prevent accidental sends while composing CJK text. (#25178) Thanks @bottotl.
- macOS/Voice wake routing: default forwarded voice-wake transcripts to the
webchatchannel (instead of ambiguouslastrouting) so local voice prompts stay pinned to the control chat surface unless explicitly overridden. (#25440) Thanks @chilu18. - macOS/Gateway launch: prefer an available
openclawbinary before pnpm/node runtime fallback when resolving local gateway commands, so local startup no longer fails on hosts with broken runtime discovery. (#25512) Thanks @chilu18. - macOS/Menu bar: stop reusing the injector delegate for the "Usage cost (30 days)" submenu to prevent recursive submenu injection loops when opening cost history. (#25341) Thanks @yingchunbai.
- macOS/WebChat panel: fix rounded-corner clipping by using panel-specific visual-effect blending and matching corner masking on both effect and hosting layers. (#22458) Thanks @apethree and @agisilaos.
- Windows/Exec shell selection: prefer PowerShell 7 (
pwsh) discovery (Program Files, ProgramW6432, PATH) before falling back to Windows PowerShell 5.1, fixing&&command chaining failures on Windows hosts with PS7 installed. (#25684, #25638) Thanks @zerone0x. - Windows/Media safety checks: align async local-file identity validation with sync-safe-open behavior by treating win32
dev=0stats as unknown-device fallbacks (while keeping strict dev checks when both sides are non-zero), fixing falseLocal media path is not safe to readdrops for local attachments/TTS/images. (#25708, #21989, #25699, #25878) Thanks @kevinWangSheng. - iMessage/Reasoning safety: harden iMessage echo suppression with outbound
messageIdmatching (plus scoped text fallback), and enforce reasoning-payload suppression on routed outbound delivery paths to prevent hidden thinking text from being sent as user-visible channel messages. (#25897, #1649, #25757) Thanks @rmarr and @Iranb. - Providers/OpenRouter/Auth profiles: bypass auth-profile cooldown/disable windows for OpenRouter, so provider failures no longer put OpenRouter profiles into local cooldown and stale legacy cooldown markers are ignored in fallback and status selection paths. (#25892) Thanks @alexanderatallah for raising this and @vincentkoc for the fix.
- Providers/Google reasoning: sanitize invalid negative
thinkingBudgetpayloads for Gemini 3.1 requests by dropping-1budgets and mapping configured reasoning effort tothinkingLevel, preventing malformed reasoning payloads ongoogle-generative-ai. (#25900) - Providers/SiliconFlow: normalize
thinking="off"tothinking: nullforPro/*model payloads to avoid provider-side 400 loops and misleading compaction retries. (#25435) Thanks @Zjianru. - Models/Bedrock auth: normalize additional Bedrock provider aliases (
bedrock,aws-bedrock,aws_bedrock,amazon bedrock) to canonicalamazon-bedrock, ensuring auth-mode resolution consistently selects AWS SDK fallback. (#25756) Thanks @fwhite13. - Models/Providers: preserve explicit user
reasoningoverrides when merging provider model config with built-in catalog metadata, soreasoning: falseis no longer overwritten by catalog defaults. (#25314) Thanks @lbo728. - Gateway/Auth: allow trusted-proxy authenticated Control UI websocket sessions to skip device pairing when device identity is absent, preventing false
pairing requiredfailures behind trusted reverse proxies. (#25428) Thanks @SidQin-cyber. - CLI/Memory search: accept
--query <text>foropenclaw memory search(while keeping positional query support), and emit a clear error when neither form is provided. (#25904, #25857) Thanks @niceysam and @stakeswky. - CLI/Doctor: correct stale recovery hints to use valid commands (
openclaw gateway status --deepandopenclaw configure --section model). (#24485) Thanks @chilu18. - Doctor/Sandbox: when sandbox mode is enabled but Docker is unavailable, surface a clear actionable warning (including failure impact and remediation) instead of a mild “skip checks” note. (#25438) Thanks @mcaxtr.
- Doctor/Plugins: auto-enable now resolves third-party channel plugins by manifest plugin id (not channel id), preventing invalid
plugins.entries.<channelId>writes when ids differ. (#25275) Thanks @zerone0x. - Config/Plugins: treat stale removed
google-antigravity-authplugin references as compatibility warnings (not hard validation errors) acrossplugins.entries,plugins.allow,plugins.deny, andplugins.slots.memory, so startup no longer fails after antigravity removal. (#25538, #25862) Thanks @chilu18. - Config/Meta: accept numeric
meta.lastTouchedAttimestamps and coerce them to ISO strings, preserving compatibility with agent edits that writeDate.now()values. (#25491) Thanks @mcaxtr. - Usage accounting: parse Moonshot/Kimi
cached_tokensfields (includingprompt_tokens_details.cached_tokens) into normalized cache-read usage metrics. (#25436) Thanks @Elarwei001. - Agents/Tool dispatch: await block-reply flush before tool execution starts so buffered block replies preserve message ordering around tool calls. (#25427) Thanks @SidQin-cyber.
- Agents/Billing classification: prevent long assistant/user-facing text from being rewritten as billing failures while preserving explicit
status/code/http 402detection for oversized structured error payloads. (#25680, #25661) Thanks @lairtonlelis. - Sessions/Tool-result guard: avoid generating synthetic
toolResultentries for assistant turns that ended withstopReason: "aborted"or"error", preventing orphaned tool-use IDs from triggering downstream API validation errors. (#25429) Thanks @mikaeldiakhate-cell. - Auto-reply/Reset hooks: guarantee native
/newand/resetflows emit command/reset hooks even on early-return command paths, with dedupe protection to avoid double hook emission. (#25459) Thanks @chilu18. - Hooks/Slug generator: resolve session slug model from the agent’s effective model (including defaults/fallback resolution) instead of raw agent-primary config only. (#25485) Thanks @SudeepMalipeddi.
- Sandbox/FS bridge tests: add regression coverage for dash-leading basenames to confirm sandbox file reads resolve to absolute container paths (and avoid shell-option misdiagnosis for dashed filenames). (#25891) Thanks @albertlieyingadrian.
- Sandbox/FS bridge: build canonical-path shell scripts with newline separators (not
;joins) to avoid POSIXshdo;syntax errors that broke sandbox file/image read-write operations. (#25737, #25824, #25868) Thanks @DennisGoldfinger and @peteragility. - Sandbox/Config: preserve
dangerouslyAllowReservedContainerTargetsanddangerouslyAllowExternalBindSourcesduring sandbox docker config resolution so explicit bind-mount break-glass overrides reach runtime validation. (#25410) Thanks @skyer-jian. - Gateway/Security: enforce gateway auth for the exact
/api/channelsplugin root path (plus/api/channels/descendants), with regression coverage for query/trailing-slash variants and near-miss paths that must remain plugin-owned. (#25753) Thanks @bmendonca3. - Exec approvals: treat bare allowlist
*as a true wildcard for parsed executables, including unresolved PATH lookups, so global opt-in allowlists work as configured. (#25250) Thanks @widingmarcus-cyber. - iOS/Signing: improve
scripts/ios-team-id.shfor Xcode 16+ by falling back to Xcode-managed provisioning profiles, add actionable guidance when an Apple account exists but no Team ID can be resolved, and ignore Xcodexcodebuildoutput directories (apps/ios/build,apps/shared/OpenClawKit/build,Swabble/build). (#22773) Thanks @brianleach. - Control UI/Chat images: route image-click opens through a shared safe-open helper (allowing only safe URL schemes) and open new tabs with opener isolation to block tabnabbing. (#18685, #25444, #25847) Thanks @Mariana-Codebase and @shakkernerd.
- Security/Exec: sanitize inherited host execution environment before merge, canonicalize inherited PATH handling, and strip dangerous keys (
LD_*,DYLD_*,SSLKEYLOGFILE, and related injection vectors) from non-sandboxed exec runs. (#25755) Thanks @bmendonca3. - Security/Hooks: normalize hook session-key classification with trim/lowercase plus Unicode NFKC folding (for example full-width
HOOK:...) so external-content wrapping cannot be bypassed by mixed-case or lookalike prefixes. (#25750) Thanks @bmendonca3. - Security/Voice Call: add Telnyx webhook replay detection and canonicalize replay-key signature encoding (Base64/Base64URL equivalent forms dedupe together), so duplicate signed webhook deliveries no longer re-trigger side effects. (#25832) Thanks @bmendonca3.
- Security/Sandbox media: restrict sandbox media tmp-path allowances to OpenClaw-managed tmp roots instead of broad host
os.tmpdir()trust, and add outbound/channel guardrails (tmp-path lint + media-root smoke tests) to prevent regressions in local media attachment reads. Thanks @tdjackey for reporting. - Security/Sandbox media: reject hard-linked OpenClaw tmp media aliases (including symlink-to-hardlink chains) during sandbox media path resolution to prevent out-of-sandbox inode alias reads. (#25820) Thanks @bmendonca3.
- Security/Message actions: enforce local media root checks for
sendAttachmentandsetGroupIconwhensandboxRootis unset, preventing attachment hydration from reading arbitrary host files via local absolute paths. Thanks @GCXWLP for reporting. - Security/Telegram: enforce DM authorization before media download/write (including media groups) and move telegram inbound activity tracking after DM authorization, preventing unauthorized sender-triggered inbound media disk writes. Thanks @v8hid for reporting.
- Security/Workspace FS: normalize
@-prefixed paths before workspace-boundary checks (including workspace-only read/write/edit and sandbox mount path guards), preventing absolute-path escape attempts from bypassing guard validation. Thanks @tdjackey for reporting. - Security/Synology Chat: enforce fail-closed allowlist behavior for DM ingress so
dmPolicy: "allowlist"with emptyallowedUserIdsrejects all senders instead of allowing unauthorized dispatch. (#25827) Thanks @bmendonca3 for the contribution and @tdjackey for reporting. - Security/Native images: enforce
tools.fs.workspaceOnlyfor native prompt image auto-load (including history refs), preventing out-of-workspace sandbox mounts from being implicitly ingested as vision input. Thanks @tdjackey for reporting. - Security/Exec approvals: bind
system.runcommand display/approval text to full argv when shell-wrapper inline payloads carry positional argv values, and reject payload-onlyrawCommandmismatches for those wrapper-carrier forms, preventing hidden command execution under misleading approval text. Thanks @tdjackey for reporting. - Security/Exec companion host: forward canonical
system.rundisplay text (not payload-only shell snippets) to the macOS exec host, and enforce rawCommand/argv consistency there for shell-wrapper positional-argv carriers and env-modifier preludes, preventing companion-side approval/display drift. Thanks @tdjackey for reporting. - Security/Exec approvals: fail closed when transparent dispatch-wrapper unwrapping exceeds the depth cap, so nested
/usr/bin/envchains cannot bypass shell-wrapper approval gating inallowlist+ask=on-missmode. Thanks @tdjackey for reporting. - Security/Exec: limit default safe-bin trusted directories to immutable system paths (
/bin,/usr/bin) and require explicit opt-in (tools.exec.safeBinTrustedDirs) for package-manager/user bin paths (for example Homebrew), add security-audit findings for risky trusted-dir choices, warn at runtime when explicitly trusted dirs are group/world writable, and add doctor hints when configuredsafeBinsresolve outside trusted dirs. Thanks @tdjackey for reporting. - Security/Sandbox: canonicalize bind-mount source paths via existing-ancestor realpath so symlink-parent + non-existent-leaf paths cannot bypass allowed-source-roots or blocked-path checks. Thanks @tdjackey.