Commit Graph

5206 Commits

Author SHA1 Message Date
Peter Steinberger
0d0effd9d4 fix: preserve sessions path containment after legacy absolute-path normalization (#15323) (thanks @mudrii) 2026-02-13 15:13:39 +01:00
Ion Mudreac
abcdbd8afc fix(sessions): normalize absolute sessionFile paths for v2026.2.12 compatibility
Older OpenClaw versions stored absolute sessionFile paths in sessions.json.
v2026.2.12 added path traversal security that rejected these absolute paths,
breaking all Telegram group handlers with 'Session file path must be within
sessions directory' errors.

Changes:
- resolvePathWithinSessionsDir() now normalizes absolute paths that resolve
  within the sessions directory, converting them to relative before validation
- Added 3 tests for absolute path handling (within dir, with topic, outside dir)

Fixes #15283
Closes #15214, #15237, #15216, #15152, #15213
2026-02-13 15:09:13 +01:00
大猫子
edfdd12d37 TTS: add missing OpenAI voices (ballad, cedar, juniper, marin, verse) (openclaw#11020) thanks @lailoo
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: ${pr_author_login} <${coauthor_email}>
Co-authored-by: ${tak_name} <${tak_email}>
2026-02-13 07:54:00 -06:00
Peter Steinberger
ee31cd47b4 fix: close OC-02 gaps in ACP permission + gateway HTTP deny config (#15390) (thanks @aether-ai-agent) 2026-02-13 14:30:06 +01:00
aether-ai-agent
749e28dec7 fix(security): block dangerous tools from HTTP gateway and fix ACP auto-approval (OC-02)
Two critical RCE vectors patched:

Vector 1 - Gateway HTTP /tools/invoke:
- Add DEFAULT_GATEWAY_HTTP_TOOL_DENY blocking sessions_spawn,
  sessions_send, gateway, whatsapp_login from HTTP invocation
- Apply deny filter after existing policy cascade, before tool lookup
- Add gateway.tools.{allow,deny} config override in GatewayConfig

Vector 2 - ACP client auto-approval:
- Replace blind allow_once selection with danger-aware permission handler
- Dangerous tools (exec, sessions_spawn, etc.) require interactive confirmation
- Safe tools retain auto-approve behavior (backward compatible)
- Empty options array now denied (was hardcoded "allow")
- 30s timeout auto-denies to prevent hung sessions

CWE-78 | CVSS:3.1 9.8 Critical
2026-02-13 14:30:06 +01:00
Peter Steinberger
8899f9e94a perf(test): optimize heavy suites and stabilize lock timing 2026-02-13 13:29:07 +00:00
Harrington-bot
771c7ba14e test: add pickAsset unit tests for architecture-aware signal-cli install 2026-02-13 14:25:26 +01:00
Harrington-bot
eb4a0a84f2 fix: use Homebrew for signal-cli install on non-x64 architectures 2026-02-13 14:25:26 +01:00
Peter Steinberger
990413534a fix: land multi-agent session path fix + regressions (#15103) (#15448)
Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-02-13 14:17:24 +01:00
JINNYEONG KIM
94763cd87d Fix OpenAI/Codex tool call id sanitization for transcript policy (#15279) 2026-02-13 11:39:51 +00:00
loiie45e
07faab6ac3 openai-codex: bridge OAuth profiles into pi auth.json for model discovery (#15184) 2026-02-13 11:39:37 +00:00
Lucky
e3cb2564d7 Agents: allow gpt-5.3-codex-spark in fallback and thinking (#14990)
* Agents: allow gpt-5.3-codex-spark in fallback and thinking

* Fix: model picker issue for openai-codex/gpt-5.3-codex-spark

Fixed an issue in the model picker.
2026-02-13 11:39:22 +00:00
Peter Steinberger
417509c539 test: stabilize local-timestamp assertion in session resets 2026-02-13 04:58:11 +00:00
青雲
fd076eb43a fix: /status shows incorrect context percentage — totalTokens clamped to contextTokens (#15114) (#15133)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a489669fc7
Co-authored-by: echoVic <16428813+echoVic@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 23:52:19 -05:00
Masataka Shinohara
b93ad2cd48 fix(slack): populate thread session with existing thread history (#7610)
* feat(slack): populate thread session with existing thread history

When a new session is created for a Slack thread, fetch and inject
the full thread history as context. This preserves conversation
continuity so the bot knows what it previously said in the thread.

- Add resolveSlackThreadHistory() to fetch all thread messages
- Add ThreadHistoryBody to context payload
- Use thread history instead of just thread starter for new sessions

Fixes #4470

* chore: remove redundant comments

* fix: use threadContextNote in queue body

* fix(slack): address Greptile review feedback

- P0: Use thread session key (not base session key) for new-session check
  This ensures thread history is injected when the thread session is new,
  even if the base channel session already exists.

- P1: Fetch up to 200 messages and take the most recent N
  Slack API returns messages in chronological order (oldest first).
  Previously we took the first N, now we take the last N for relevant context.

- P1: Batch resolve user names with Promise.all
  Avoid N sequential API calls when resolving user names in thread history.

- P2: Include file-only messages in thread history
  Messages with attachments but no text are now included with a placeholder
  like '[attached: image.png, document.pdf]'.

- P2: Add documentation about intentional 200-message fetch limit
  Clarifies that we intentionally don't paginate; 200 covers most threads.

* style: add braces for curly lint rule

* feat(slack): add thread.initialHistoryLimit config option

Allow users to configure the maximum number of thread messages to fetch
when starting a new thread session. Defaults to 20. Set to 0 to disable
thread history fetching entirely.

This addresses the optional configuration request from #2608.

* chore: trigger CI

* fix(slack): ensure isNewSession=true on first thread turn

recordInboundSession() in prepare.ts creates the thread session entry
before session.ts reads the store, causing isNewSession to be false
on the very first user message in a thread. This prevented thread
context (history/starter) from being injected.

Add IsFirstThreadTurn flag to message context, set when
readSessionUpdatedAt() returns undefined for the thread session key.
session.ts uses this flag to force isNewSession=true.

* style: format prepare.ts for oxfmt

* fix: suppress InboundHistory/ThreadStarterBody when ThreadHistoryBody present (#13912)

When ThreadHistoryBody is fetched from the Slack API (conversations.replies),
it already contains pending messages and the thread starter. Passing both
InboundHistory and ThreadStarterBody alongside ThreadHistoryBody caused
duplicate content in the LLM context on new thread sessions.

Suppress InboundHistory and ThreadStarterBody when ThreadHistoryBody is
present, since it is a strict superset of both.

* remove verbose comment

* fix(slack): paginate thread history context fetch

* fix(slack): wire session file path options after main merge

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 05:51:04 +01:00
Peter Steinberger
78ec0a1edf fix: stabilize test runner and daemon-cli compat 2026-02-13 04:45:04 +00:00
Peter Steinberger
ba7dccc49d test: speed up test suite and trim redundant onboarding tests 2026-02-13 04:30:48 +00:00
Gustavo Madeira Santana
ac41176532 Auto-reply: fix non-default agent session transcript path resolution (#15154)
* Auto-reply: fix non-default agent transcript path resolution

* Auto-reply: harden non-default agent transcript lookups

* Auto-reply: harden session path resolution across agent stores
2026-02-12 23:23:12 -05:00
Peter Steinberger
79a38858ae fix: preserve off-mode semantics in auto reply threading (#14976) (thanks @Diaspar4u) 2026-02-13 05:22:14 +01:00
Andrey
3d89f0f14a fix(reply): auto-inject replyToCurrent for reply threading
replyToMode "first"/"all" only filters replyToId but never generates
it — that required the LLM to emit [[reply_to_current]] tags. Inject
replyToCurrent:true on all payloads so applyReplyTagsToPayload sets
replyToId=currentMessageId, then let the existing mode filter decide
which replies keep threading (first only, all, or off).

Covers both final reply path (reply-payloads.ts) and block streaming
path (agent-runner-execution.ts).
2026-02-13 05:22:14 +01:00
Marcus Castro
39ee708df6 fix(outbound): return error instead of silently redirecting to allowList[0] (#13578) 2026-02-13 05:20:03 +01:00
Peter Steinberger
a43136c85e fix: align slack thread footer metadata with reply semantics (#14625) (thanks @bennewton999) 2026-02-13 05:18:06 +01:00
Ben Newton
2b9d5e6e30 feat(slack): include thread metadata (thread_ts, parent_user_id) in agent context
Adds thread_ts and parent_user_id to the Slack message footer for thread
replies, giving agents awareness of thread context. Top-level messages
remain unchanged.

Includes tests verifying:
- Thread replies include thread_ts and parent_user_id in footer
- Top-level messages exclude thread metadata
2026-02-13 05:18:06 +01:00
seheepeak
23e4183608 fix(sandbox): force network bridge for browser container (#6961) 2026-02-13 05:17:17 +01:00
Kentaro Kuribayashi
c6ecd2a044 fix: replace file-based session store lock with in-process Promise chain mutex (#14498)
* fix: replace file-based session store lock with in-process Promise chain mutex

Node.js is single-threaded, so file-based locking (open('wx') + polling +
stale eviction) is unnecessary and causes timeouts under heavy session load.

Replace with a simple per-storePath Promise chain that serializes access
without any filesystem overhead.

In a 1159-session environment over 3 hours:
- Lock timeouts: 25
- Stuck sessions: 157 (max 1031s, avg 388s)
- Slow listeners: 39 (max 265s, avg 70s)

Root cause: during sessions.json file I/O, await yields control and other
lock requests hit the 10s timeout waiting for the .lock file to be released.

* test: add comprehensive tests for Promise chain mutex lock

- Concurrent access serialization (10 parallel writers, counter integrity)
- Error resilience (single & multiple consecutive throws don't poison queue)
- Independent storePath parallelism (different paths run concurrently)
- LOCK_QUEUES cleanup after completion and after errors
- No .lock file created on disk

Also fix: store caught promise in LOCK_QUEUES to avoid unhandled rejection
warnings when queued fn() throws.

* fix: add timeout to Promise chain mutex to prevent infinite hangs on Windows

* fix(session-store): enforce strict queue timeout + cross-process lock

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 05:12:59 +01:00
Marcus Castro
13bfd9da83 fix: thread replyToId and threadId through message tool send action (#14948)
* fix: thread replyToId and threadId through message tool send action

* fix: omit replyToId/threadId from gateway send params

* fix: add threading seam regression coverage (#14948) (thanks @mcaxtr)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:55:20 +01:00
Marcus Castro
e355f6e093 fix(security): distinguish webhooks from internal hooks in audit summary (#13474)
* fix(security): distinguish webhooks from internal hooks in audit summary

The attack surface summary reported a single 'hooks: disabled/enabled' line
that only checked the external webhook endpoint (hooks.enabled), ignoring
internal hooks (hooks.internal.enabled). Users who enabled internal hooks
(session-memory, command-logger, etc.) saw 'hooks: disabled' and thought
something was broken.

Split into two separate lines:
- hooks.webhooks: disabled/enabled
- hooks.internal: disabled/enabled

Fixes #13466

* test(security): move attack surface tests to focused test file

Move the 3 new hook-distinction tests from the monolithic audit.test.ts
(1,511 lines) into a dedicated audit-extra.sync.test.ts that tests
collectAttackSurfaceSummaryFindings directly. Avoids growing the
already-large test file and keeps tests focused on the changed unit.

* fix: add changelog entry for security audit hook split (#13474) (thanks @mcaxtr)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:46:27 +01:00
Marcus Castro
e90caa66d8 fix(exec): allow heredoc operator (<<) in allowlist security mode (#13811)
* fix(exec): allow heredoc operator (<<) in allowlist security mode

* fix: allow multiline heredoc parsing in exec approvals (#13811) (thanks @mcaxtr)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:41:51 +01:00
Peter Steinberger
7c25696ab0 fix(config): enforce default-free persistence in write path 2026-02-13 04:41:04 +01:00
Marcus Castro
2a9745c9a1 fix(config): redact resolved field in config snapshots
The newly added 'resolved' field contains secrets after ${ENV}
substitution. This commit ensures redactConfigSnapshot also redacts
the resolved field to prevent credential leaks in config.get responses.
2026-02-13 04:41:04 +01:00
Marcus Castro
3189e2f11b fix(config): add resolved field to ConfigFileSnapshot for pre-defaults config
The initial fix using snapshot.parsed broke configs with $include directives.
This commit adds a new 'resolved' field to ConfigFileSnapshot that contains
the config after $include and ${ENV} substitution but BEFORE runtime defaults
are applied. This is now used by config set/unset to avoid:
1. Breaking configs with $include directives
2. Leaking runtime defaults into the written config file

Also removes applyModelDefaults from writeConfigFile since runtime defaults
should only be applied when loading, not when writing.
2026-02-13 04:41:04 +01:00
Marcus Castro
9e8d9f114d fix(cli): use raw config instead of runtime-merged config in config set/unset
Fixes #6070

The config set/unset commands were using snapshot.config (which contains
runtime-merged defaults) instead of snapshot.parsed (the raw user config).
This caused runtime defaults like agents.defaults to leak into the written
config file when any value was set or unset.

Changed both set and unset commands to use structuredClone(snapshot.parsed)
to preserve only user-specified config values.
2026-02-13 04:41:04 +01:00
George Pickett
a067565db5 fix: pass sandbox docker env into containers (#15138) (thanks @stevebot-alive) 2026-02-12 19:39:22 -08:00
Steve (OpenClaw)
92567765e6 fix(sandbox): pass docker.env into sandbox container 2026-02-12 19:39:22 -08:00
Joseph Krug
40aff672c1 fix: prevent heartbeat scheduler silent death from wake handler race (#15108)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: fd7165b935
Co-authored-by: joeykrug <5925937+joeykrug@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 22:30:21 -05:00
Marcus Castro
ec44e262be fix(security): prevent String(undefined) coercion in credential inputs (#12287)
* fix(security): prevent String(undefined) coercion in credential inputs

When a prompter returns undefined (due to cancel, timeout, or bug),
String(undefined).trim() produces the literal string "undefined" instead
of "". This truthy string prevents secure fallbacks from triggering,
allowing predictable credential values (e.g., gateway password = "undefined").

Fix all 8 occurrences by using String(value ?? "").trim(), which correctly
yields "" for null/undefined inputs and triggers downstream validation or
fallback logic.

Fixes #8054

* fix(security): also fix String(undefined) in api-provider credential inputs

Address codex review feedback: 4 additional occurrences of the unsafe
String(variable).trim() pattern in auth-choice.apply.api-providers.ts
(Cloudflare Account ID, Gateway ID, synthetic API key inputs + validators).

* fix(test): strengthen password coercion test per review feedback

* fix(security): harden credential prompt coercion

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:25:05 +01:00
Peter Steinberger
711597c02b fix(update): repair daemon-cli compat exports after self-update 2026-02-13 04:08:13 +01:00
Marcus Castro
585c9a7265 fix(session): preserve verbose/thinking/tts overrides across /new and /reset (openclaw#10881) thanks @mcaxtr
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:27:12 -06:00
Peter Steinberger
cd50b5ded2 fix(onboarding): exit cleanly after web ui hatch 2026-02-13 03:20:32 +01:00
Sk Akram
7cbf607a8f feat: expose /compact command in Telegram native menu (openclaw#10352) thanks @akramcodez
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: akramcodez <179671552+akramcodez@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:17:25 -06:00
Milofax
89503e1451 fix(browser): hide navigator.webdriver from reCAPTCHA v3 detection (openclaw#10735) thanks @Milofax
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: Milofax <2537423+Milofax@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:16:28 -06:00
JustasM
57d0f65e7d CLI: add plugins uninstall command (#5985) (openclaw#6141) thanks @JustasMonkev
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: JustasMonkev <59362982+JustasMonkev@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:11:26 -06:00
Shadow
34c304727b Discord: honor Administrator in permission checks 2026-02-12 19:53:22 -06:00
Shadow
22fe30c1df fix: add discord role allowlists (#10650) (thanks @Minidoracat) 2026-02-12 19:52:24 -06:00
Minidoracat
f7adc21d31 fix: exclude role-restricted bindings from guild-only matching 2026-02-12 19:52:24 -06:00
Minidoracat
e084f07420 fix: add missing role-based type definitions for RBAC routing 2026-02-12 19:52:24 -06:00
Minidoracat
ad508c8c89 fix: use member.roles as string[] per Discord API types 2026-02-12 19:52:24 -06:00
Minidoracat
e1e6e3f477 fix: add curly braces to resolve-route.ts for eslint(curly) compliance 2026-02-12 19:52:24 -06:00
Minidoracat
4bf06e7824 Discord: add unit tests for role-based agent routing 2026-02-12 19:52:24 -06:00
Minidoracat
334a291fb7 Discord: pass member role IDs to agent route resolution 2026-02-12 19:52:24 -06:00