fix(clawhub): resolve auth token for skill browsing#53017
Conversation
🔒 Aisle Security AnalysisWe found 2 potential security issue(s) in this PR:
1. 🔵 Potential DoS via repeated unbounded config file read + JSON.parse in resolveClawHubAuthToken
Description
Issues:
Vulnerable code: const raw = await fs.readFile(resolveClawHubConfigPath(), "utf8");
return extractTokenFromClawHubConfig(JSON.parse(raw));return (
readNonEmptyString(record.accessToken) ??
...
extractTokenFromClawHubConfig(record.auth) ??
extractTokenFromClawHubConfig(record.session) ??
extractTokenFromClawHubConfig(record.credentials) ??
extractTokenFromClawHubConfig(record.user)
);const token = params.token?.trim() || (await resolveClawHubAuthToken());RecommendationAdd resource limits and avoid repeated parsing:
Example (size check + caching + depth cap): let cachedToken: string | undefined;
let cachedAt = 0;
const TOKEN_TTL_MS = 60_000;
const MAX_CONFIG_BYTES = 1_000_000; // 1MB
const MAX_DEPTH = 20;
function extractTokenFromClawHubConfig(value: unknown, depth = 0): string | undefined {
if (depth > MAX_DEPTH || !value || typeof value !== "object") return undefined;
const record = value as any;
return (
readNonEmptyString(record.accessToken) ??
readNonEmptyString(record.authToken) ??
readNonEmptyString(record.apiToken) ??
readNonEmptyString(record.token) ??
extractTokenFromClawHubConfig(record.auth, depth + 1) ??
extractTokenFromClawHubConfig(record.session, depth + 1) ??
extractTokenFromClawHubConfig(record.credentials, depth + 1) ??
extractTokenFromClawHubConfig(record.user, depth + 1)
);
}
export async function resolveClawHubAuthToken(): Promise<string | undefined> {
if (cachedToken && Date.now() - cachedAt < TOKEN_TTL_MS) return cachedToken;
const envToken = process.env.OPENCLAW_CLAWHUB_TOKEN?.trim()
|| process.env.CLAWHUB_TOKEN?.trim()
|| process.env.CLAWHUB_AUTH_TOKEN?.trim();
if (envToken) return envToken;
try {
const configPath = resolveClawHubConfigPath();
const st = await fs.stat(configPath);
if (st.size > MAX_CONFIG_BYTES) return undefined;
const raw = await fs.readFile(configPath, "utf8");
cachedToken = extractTokenFromClawHubConfig(JSON.parse(raw));
cachedAt = Date.now();
return cachedToken;
} catch {
return undefined;
}
}This prevents pathological config files from causing CPU/memory spikes and avoids repeating expensive operations on every ClawHub request. 2. 🔵 Credential leakage / SSRF risk: Authorization token auto-attached to user-controlled ClawHub baseUrl
DescriptionThe ClawHub HTTP helper now automatically resolves an auth token from environment variables or a local config file and attaches it as a Because Impact:
Vulnerable code: const url = buildUrl(params);
const token = params.token?.trim() || (await resolveClawHubAuthToken());
...
headers: token ? { Authorization: `Bearer ${token}` } : undefined,RecommendationDo not automatically attach a credential to arbitrary origins. Suggested mitigations (combine as appropriate):
function shouldAttachClawHubAuth(url: URL): boolean {
return url.protocol === "https:" && url.hostname === "clawhub.ai";
}
const url = buildUrl(params);
const token = params.token?.trim() || (await resolveClawHubAuthToken());
const headers = token && shouldAttachClawHubAuth(url)
? { Authorization: `Bearer ${token}` }
: undefined;
Analyzed PR: #53017 at commit Last updated on: 2026-03-23T17:06:55Z |
Greptile SummaryThis PR fixes two related issues with ClawHub skill browsing: auth tokens were not being resolved from the environment or local config before making marketplace requests, and browse-all queries were hitting an authenticated list endpoint that returned 429s or empty results instead of the public search endpoint. Changes:
The one minor note is that Confidence Score: 5/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/infra/clawhub.ts
Line: 434
Comment:
**Per-request filesystem read for token resolution**
`resolveClawHubAuthToken()` reads `config.json` from disk on every call to `clawhubRequest()`. Chained operations — for example `installSkillFromClawHub` which calls both `fetchClawHubSkillDetail` and `downloadClawHubSkillArchive` — will read the file twice. For a CLI tool this is negligible, but a simple module-level memoization (resolved value stored in a process-lifetime variable on first read) would eliminate the redundant I/O if the call pattern ever becomes more frequent. Not a blocking concern for current usage.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "docs(changelog): note clawhub skill auth..." | Re-trigger Greptile |
| params: ClawHubRequestParams, | ||
| ): Promise<{ response: Response; url: URL }> { | ||
| const url = buildUrl(params); | ||
| const token = params.token?.trim() || (await resolveClawHubAuthToken()); |
There was a problem hiding this comment.
Per-request filesystem read for token resolution
resolveClawHubAuthToken() reads config.json from disk on every call to clawhubRequest(). Chained operations — for example installSkillFromClawHub which calls both fetchClawHubSkillDetail and downloadClawHubSkillArchive — will read the file twice. For a CLI tool this is negligible, but a simple module-level memoization (resolved value stored in a process-lifetime variable on first read) would eliminate the redundant I/O if the call pattern ever becomes more frequent. Not a blocking concern for current usage.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/infra/clawhub.ts
Line: 434
Comment:
**Per-request filesystem read for token resolution**
`resolveClawHubAuthToken()` reads `config.json` from disk on every call to `clawhubRequest()`. Chained operations — for example `installSkillFromClawHub` which calls both `fetchClawHubSkillDetail` and `downloadClawHubSkillArchive` — will read the file twice. For a CLI tool this is negligible, but a simple module-level memoization (resolved value stored in a process-lifetime variable on first read) would eliminate the redundant I/O if the call pattern ever becomes more frequent. Not a blocking concern for current usage.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2bca58323f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| params: ClawHubRequestParams, | ||
| ): Promise<{ response: Response; url: URL }> { | ||
| const url = buildUrl(params); | ||
| const token = params.token?.trim() || (await resolveClawHubAuthToken()); |
There was a problem hiding this comment.
Gate auto-resolved auth token by trusted registry host
Falling back to resolveClawHubAuthToken() for every request means any call that omits token now sends a bearer token to whatever baseUrl is supplied. In the current call chain, updateSkillsFromClawHub can source baseUrl from per-skill origin metadata (src/agents/skills-clawhub.ts:317), so a tampered workspace can cause openclaw skills update to exfiltrate the user’s local ClawHub token to an attacker-controlled host; before this change those requests were unauthenticated. Restrict auto-token attachment to trusted hosts (or require explicit opt-in) to avoid credential leakage.
Useful? React with 👍 / 👎.
* fix(clawhub): resolve auth token for skill browsing * docs(changelog): note clawhub skill auth fix
* fix(clawhub): resolve auth token for skill browsing * docs(changelog): note clawhub skill auth fix
* fix(clawhub): resolve auth token for skill browsing * docs(changelog): note clawhub skill auth fix
* fix(clawhub): resolve auth token for skill browsing * docs(changelog): note clawhub skill auth fix
* fix(clawhub): resolve auth token for skill browsing * docs(changelog): note clawhub skill auth fix
* fix(clawhub): resolve auth token for skill browsing * docs(changelog): note clawhub skill auth fix
…claw#105) * fix(web-search): mark DuckDuckGo experimental * docs(tools): update DuckDuckGo Search for landed plugin code - Mark as experimental (not just unofficial) - Add region and safeSearch tool parameters (from DDG schema) - Add plugin config example for region/safeSearch defaults - Document auto-detection order (100 = last) - Note SafeSearch defaults to moderate - Verified against extensions/duckduckgo/src/ * fix(agents): deny local MEDIA paths for MCP results * Usage: include reset and deleted session archives (openclaw#43215) Merged via squash. Prepared head SHA: 49ed6c2 Co-authored-by: rcrick <[email protected]> Co-authored-by: frankekn <[email protected]> Reviewed-by: @frankekn * docs(tools): soften DDG wording (scrapes -> pulls/gathers) * fix(build): add stable memory-cli dist entry (openclaw#51759) Co-authored-by: oliviareid-svg <[email protected]> Co-authored-by: Frank <[email protected]> * refactor!: drop legacy CLAWDBOT env compatibility * refactor!: remove moltbot state-dir migration fallback * fix(gateway): preserve async hook ingress provenance * fix(ci): write dist build stamp after builds * perf: trim vitest hot imports and refresh manifests * fix(security): unwrap time dispatch wrappers * fix(plugin-sdk): fall back to src root alias files * fix(ci): skip docs-only preflight pnpm audit * docs(changelog): note time exec approval fix * docs: refresh plugin-sdk api baseline * fix(runtime): make dist-runtime staging idempotent * fix(media): bound remote error-body snippet reads * fix(gateway): gate internal command persistence mutations * fix: restrict remote marketplace plugin sources * fix(runtime): skip peer resolution for bundled plugin deps * docs(agents): prefer current test model examples * fix(exec): escape invisible approval filler chars * test(models): refresh example model fixtures * fix(security): unify dispatch wrapper approval hardening * fix(security): harden explicit-proxy SSRF pinning * fix: gate synology chat reply name matching * docs: clarify sessions_spawn ACP vs subagent policies * refactor(exec): split wrapper resolution modules * refactor(exec): make dispatch wrapper semantics spec-driven * refactor(exec): share wrapper trust planning * refactor(exec): rename wrapper plans for trust semantics * fix: include .npmrc in onboard docker build * test: trim docker live auth mounts * Docs: refresh config baseline for Synology Chat * refactor: clarify synology delivery identity names * refactor: centralize synology dangerous name matching * refactor: narrow synology legacy name lookup * refactor: audit synology dangerous name matching * refactor: dedupe synology config schema * fix: normalize scoped vitest filter paths * fix(voice-call): harden webhook pre-auth guards * fix(synology-chat): fail closed shared webhook paths * docs: credit nexrin in synology changelog * test: fix base vitest thread regressions * test: finish base vitest thread fixture fixes * test(voice-call): accept oversize webhook socket resets * test: honor env auth in gateway live probes * fix: harden plugin docker e2e * Docs: align MiniMax examples with M2.7 * fix(ci): restore stale guardrails and baselines * Test: isolate qr dashboard integration suite * Gateway: resolve fallback plugin context lazily * fix: bind bootstrap setup codes to node profile * fix(tlon): unify settings reconciliation semantics * refactor(synology-chat): type startup webhook path policy * docs(synology-chat): clarify multi-account webhook paths * refactor: unify minimax model and failover live policies * docs: sync minimax m2.7 references * fix: harden Windows Parallels smoke installs * docs: reorder unreleased changelog by user impact * refactor: remove embedded runner cwd mutation * Infra: support shell carrier allow-always approvals * refactor: centralize bootstrap profile handling * refactor: reuse canonical setup bootstrap profile * fix(plugin-sdk): resolve hashed diagnostic events chunks * fix(plugin-sdk): normalize hashed diagnostic event exports * test: fix ci env-sensitive assertions * fix(gateway): fail closed on unresolved discovery endpoints * feat: add slash plugin installs * fix(media): block remote-host file URLs in loaders * fix(media): harden secondary local path seams * test: harden no-isolate reply teardown * docs(changelog): add Windows media security fix * refactor(gateway): centralize discovery target handling * test: narrow live transcript scaffolding strip * test: fix ci docs drift and bun qr exit handling * fix(browser): enforce node browser proxy allowProfiles * refactor(media): share local file access guards * test: stabilize ci test harnesses * test: harden no-isolate test module resets * fix(plugins): preserve live hook registry during gateway runs * test: fix channel summary registry setup * test: harden isolated test mocks * chore(plugins): remove opik investigation checkpoints * ACPX: align pinned runtime version (openclaw#52730) * ACPX: align pinned runtime version * ACPX: drop version example from help text * test: stop leaking image workspace temp dirs * fix(android): gate canvas bridge to trusted pages (openclaw#52722) * fix(android): gate canvas bridge to trusted pages * fix(changelog): note android canvas bridge gating * Update apps/android/app/src/main/java/ai/openclaw/app/node/CanvasActionTrust.kt Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * fix(android): snapshot canvas URL on UI thread --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * test: isolate base vitest thread blockers * fix: sync agent and autoreply e2e updates * test: harden no-isolate mocked module resets * docs: reorder unreleased changelog * fix(changelog): note windows media path guardrails (openclaw#52738) * fix: alphabetize web search provider listings * docs: clarify unreleased breaking changes * test: harden ci isolated mocks * fix: align websocket stream fallback types * test: finish no-isolate suite hardening * style: format image-generation runtime tests * fix(memory-core): register memory tools independently to prevent coupled failure (openclaw#52668) Merged via admin squash because current required CI failures are inherited from base and match latest `main` failures outside this PR's `memory-core` surface. Prepared head SHA: df7f968 Co-authored-by: artwalker <[email protected]> Reviewed-by: @frankekn * fix(status): recompute fallback context window (openclaw#51795) * fix(status): recompute fallback context window * fix(status): keep live context token caps on fallback * fix(status): preserve fallback runtime context windows * fix(status): preserve configured fallback context caps * fix(status): keep provider-aware transcript context lookups * fix(status): preserve explicit fallback context caps * fix(status): clamp fallback configured context caps * fix(status): keep raw runtime slash ids * fix(status): refresh plugin-sdk api baseline * fix(status): preserve fallback context lookup * test(status): refresh plugin-sdk api baseline * fix(status): keep runtime slash-id context lookup --------- Co-authored-by: create <[email protected]> Co-authored-by: Frank Yang <[email protected]> Co-authored-by: RichardCao <[email protected]> * fix(telegram): make buttons schema optional in message tool The Telegram plugin injects a `buttons` property into the message tool schema via `createMessageToolButtonsSchema()`, but without wrapping it in `Type.Optional()`. This causes TypeBox to include `buttons` in the JSON Schema `required` array. In isolated sessions (e.g. cron jobs) where no `currentChannel` is set, all plugin schemas are merged into the message tool. When the LLM calls the message tool without a `buttons` parameter, AJV validation fails with: `buttons: must have required property 'buttons'`. Wrap the buttons schema in `Type.Optional()` so it is not required. * fix: keep message-tool buttons optional for Telegram and Mattermost (openclaw#52589) (thanks @tylerliu612) * test: update codex test fixtures to gpt-5.4 * fix: repair runtime seams after rebase * fix: restore Telegram topic announce delivery (openclaw#51688) (thanks @mvanhorn) When `replyLike.text` or `replyLike.caption` is an unexpected non-string value (edge case from some Telegram API responses), the reply body was coerced to "[object Object]" via string concatenation. Add a `typeof === "string"` guard to gracefully fall back to empty string, matching the existing pattern used for `quoteText` in the same function. Co-authored-by: Penchan <[email protected]> * docs: sync generated release baselines * test: isolate pi embedded model thread fixtures * fix: restore provider runtime lazy boundary * fix: preserve Telegram reply context text (openclaw#50500) (thanks @p3nchan) * fix: guard Telegram reply context text (openclaw#50500) (thanks @p3nchan) * fix: preserve Telegram reply caption fallback (openclaw#50500) (thanks @p3nchan) --------- Co-authored-by: Ayaan Zaidi <[email protected]> * fix: harden gateway SIGTERM shutdown (openclaw#51242) (thanks @juliabush) * fix: increase shutdown timeout to avoid SIGTERM hang * fix(telegram): abort polling fetch on shutdown to prevent SIGTERM hang * fix(gateway): enforce hard exit on shutdown timeout for SIGTERM * fix: tighten gateway shutdown watchdog * fix: harden gateway SIGTERM shutdown (openclaw#51242) (thanks @juliabush) --------- Co-authored-by: Ayaan Zaidi <[email protected]> * build: prepare 2026.3.22-beta.1 * fix: restore provider runtime lazy boundary * test: add parallels npm update smoke * test: split pi embedded model thread fixtures * fix: stop browser server tests from launching real chrome * test: stabilize live provider docker probes * fix: restart windows gateway after npm update * test: isolate server-context browser harness imports * test: inject model runtime hooks for thread-safe tests * test: snapshot ci timeout investigation * test: target gemini 3.1 flash alias * test: stabilize trigger handling and hook e2e tests * build: prepare 2026.3.22 * test: harden channel suite isolation * test: inject thread-safe deps for agent tools * test: raise timeout for slow provider auth normalization * ci: stabilize windows and bun unit lanes * test: inject thread-safe gateway and ACP seams * test: isolate pi model and reset-model thread fixtures * build: prepare 2026.3.23 * test: inject image-tool provider deps for raw threads * test: stabilize e2e module isolation * test: decouple vitest config checks from ambient env * fix: harden parallels smoke agent invocation * test: avoid repo-root perf profile artifacts * test: inject thread-safe base seams * fix: document Telegram asDocument alias (openclaw#52461) (thanks @bakhtiersizhaev) * feat(telegram): add asDocument param to message tool Adds `asDocument` as a user-facing alias for the existing `forceDocument` parameter in the message tool. When set to `true`, media files (images, videos, GIFs) are sent via `sendDocument` instead of `sendPhoto`/ `sendVideo`/`sendAnimation`, preserving the original file quality without Telegram compression. This is useful when agents need to deliver high-resolution images or uncompressed files to users via Telegram. `asDocument` is intentionally an alias rather than a replacement — the existing `forceDocument` continues to work unchanged. Changes: - src/agents/tools/message-tool.ts: add asDocument to send schema - src/agents/tools/telegram-actions.ts: OR asDocument into forceDocument - src/infra/outbound/message-action-runner.ts: same OR logic for outbound path - extensions/telegram/src/channel-actions.ts: read and forward asDocument - src/channels/plugins/actions/actions.test.ts: add test case * fix: restore channel-actions.ts to main version (rebase conflict fix) * fix(test): match asDocument test payload to actual params structure * fix(telegram): preserve forceDocument alias semantics * fix: document Telegram asDocument alias (openclaw#52461) (thanks @bakhtiersizhaev) --------- Co-authored-by: Бахтиер Сижаев <[email protected]> Co-authored-by: Ayaan Zaidi <[email protected]> * fix: refactor deepseek bundled plugin (openclaw#48762) (thanks @07akioni) * fix: declare typebox runtime dep for mattermost plugin * test: reset line webhook mocks between cases * test: split attempt spawn-workspace thread fixtures * test: remove replaced spawn-workspace monolith * refactor: isolate attempt context engine thread helpers * CI: remove npm release preview workflow (openclaw#52825) * CI: remove npm release preview workflow * Docs: align release maintainer skill with manual publish * Docs: expand release maintainer skill flow * test: stabilize gateway thread harness * test: fix status plugin pagination expectation * test: harden channel suite isolation * build: sync lockfile for mattermost plugin * fix: ensure env proxy dispatcher before MiniMax and OpenAI Codex OAuth flows (openclaw#52228) Verified: - pnpm install --frozen-lockfile - NPM_CONFIG_CACHE=/tmp/openclaw-npm-cache-52228 pnpm build - pnpm check - pnpm test:macmini (failed on inherited pre-existing plugin contract test: src/plugins/contracts/registry.contract.test.ts missing deepseek in bundled provider contract registry outside this PR surface) Co-authored-by: openperf <[email protected]> Co-authored-by: Tak Hoffman <[email protected]> * fix: restore ci gates * test: stabilize channel ci gate * docs: refresh generated config baseline * release: verify control-ui assets are included in npm tarball * release-check: include stderr/stdout when npm pack fails * release: add changelog for control UI tarball check * fix: keep session transcript pointers fresh after compaction (openclaw#50688) Co-authored-by: Frank Yang <[email protected]> * fix(msteams): isolate probe test env credentials * release: automate macOS publishing (openclaw#52853) * release: automate macOS publishing * release: keep mac appcast in openclaw repo * release: add preflight-only release workflow runs * release: keep appcast updates manual * release: generate signed appcast as workflow artifact * release: require preflight before publish * release: require mac app for every release * docs: clarify every release ships mac app * release: document Sparkle feed and SHA rules * release: keep publish flow tag-based * release: stabilize mac appcast flow * release: document local mac fallback * Update CHANGELOG.md * Improve PR template regression prompts * fix(agents): preserve anthropic thinking block order (openclaw#52961) * fix(release): ship bundled plugins in pack artifacts * fix(config): keep built-in channels out of plugin allowlists (openclaw#52964) * fix(config): keep built-in channels out of plugin allowlists * docs(changelog): note doctor whatsapp allowlist fix * docs(changelog): move doctor whatsapp fix to top * Update CHANGELOG.md * fix(config): keep built-in auto-enable idempotent * fix(release): preserve shipped channel surfaces in npm tar (openclaw#52913) * fix(channels): ship official channel catalog (openclaw#52838) * fix(release): keep shipped bundles in npm tar (openclaw#52838) * build(release): fix rebased release-check helpers (openclaw#52838) * fix(gateway): harden supervised lock and browser attach readiness * fix(matrix): avoid duplicate runtime api exports * fix(gateway): avoid probe false negatives after connect * docs(changelog): note release and matrix fixes * fix(plugins): unblock Discord/Slack message tool sends and Feishu media (openclaw#52991) * fix(plugins): unblock Discord and Slack message tool payloads * docs(changelog): note Discord Slack and Feishu message fixes * fix(channels): preserve external catalog overrides (openclaw#52988) * fix(channels): preserve external catalog overrides * fix(channels): clarify catalog precedence * fix(channels): respect overridden install specs * fix(gateway): require admin for agent session reset * fix(voice-call): stabilize plivo v2 replay keys * fix(gateway): require auth for canvas routes * fix(clawhub): resolve auth token for skill browsing (openclaw#53017) * fix(clawhub): resolve auth token for skill browsing * docs(changelog): note clawhub skill auth fix * fix(release): raise npm pack size budget * Tests: fix fresh-main regressions (openclaw#53011) * Tests: fix fresh-main regressions * Tests: avoid chat notice cache priming --------- Co-authored-by: Vincent Koc <[email protected]> * fix(config): ignore stale plugin allow entries * fix(browser): reuse running loopback browser after probe miss * fix(clawhub): honor macOS auth config path (openclaw#53034) * docs: fix nav ordering, missing pages, and stale model references - Sort providers alphabetically in docs.json nav - Sort channels alphabetically in docs.json nav (slack before synology-chat) - Add install/migrating-matrix to Maintenance nav section (was orphaned) - Remove zh-CN/plugins/architecture from nav (file does not exist) - Add Voice Call to channels index page - Add missing providers to providers index (DeepSeek, GitHub Copilot, OpenCode Go, Synthetic) - Sort providers index alphabetically - Update stale claude-3-5-sonnet model reference to claude-sonnet-4-6 in webhook docs * fix(clawhub): preserve XDG auth path on macOS * Agents: fix runtime web_search provider selection (openclaw#53020) Co-authored-by: Vincent Koc <[email protected]> * docs: fix CLI command tree, SDK import path, and tool group listing - Remove non-existent 'secrets migrate' from CLI command tree - Add actual secrets subcommands: audit, configure, apply - Add missing plugin subcommands: inspect, uninstall, update, marketplace list - Fix plugins info -> inspect (actual command name) - Add message send and broadcast subcommands to command tree - Remove misleading deprecated import from sdk-overview - Add sessions_yield and subagents to group:sessions tool group docs - Fix formatting * fix(gateway): guard openrouter auto pricing recursion (openclaw#53055) * test: refresh thread-safe agent fixtures * Release: fix npm release preflight under pnpm (openclaw#52985) Co-authored-by: Vincent Koc <[email protected]> * docs(changelog): add channel catalog override note (openclaw#52988) (openclaw#53059) * fix: harden update dev switch and refresh changelog * fix(mistral): repair max-token defaults and doctor migration (openclaw#53054) * fix(mistral): repair max-token defaults and doctor migration * fix(mistral): add missing small-model repair cap * fix(plugins): enable bundled Brave web search plugin by default (openclaw#52072) Brave is a bundled web search plugin but was missing from BUNDLED_ENABLED_BY_DEFAULT, causing it to be filtered out during provider resolution. This made web_search unavailable even when plugins.entries.brave.enabled was configured. Fixes openclaw#51937 Co-authored-by: Ubuntu <[email protected]> Co-authored-by: Vincent Koc <[email protected]> * fix(release): fail empty control ui tarballs * Revert "fix(plugins): enable bundled Brave web search plugin by default (openclaw#52072)" This reverts commit 0ea3c4d. * Telegram: preserve inbound debounce order * Telegram: fix fire-and-forget debounce order * fix(reply): refresh followup drain callbacks * Update CHANGELOG.md * fix(reply): preserve no-debounce inbound concurrency * fix(reply): clear idle followup callbacks * fix(inbound): bound tracked debounce keys * fix: preserve debounce and followup ordering (openclaw#52998) (thanks @osolmaz) * fix(discord): reply on native command auth failures (openclaw#53072) * docs(changelog): add missing recent fixes * fix: bound tracked debounce key accounting * fix packaged control ui asset lookup (openclaw#53081) * fix(cli): preserve posix default git dir * build: prepare 2026.3.23-beta.1 * test: harden canvas host undici isolation * docs(changelog): credit web search runtime fix * fix(openai-codex): bootstrap proxy on oauth refresh (openclaw#53078) Verified: - pnpm install --frozen-lockfile - pnpm exec vitest run extensions/openai/openai-codex-provider.runtime.test.ts extensions/openai/openai-provider.test.ts * release: harden preflight workflows (openclaw#53087) * release: harden preflight-only workflows * release: require main for publish runs * release: select xcode for macos workflow * release: retry flaky macos preflight steps * ci: shard bun test lane * Fix Control UI operator.read scope handling (openclaw#53110) Preserve Control UI scopes through the device-auth bypass path, normalize implied operator device-auth scopes, ignore cached under-scoped operator tokens, and degrade read-backed main pages gracefully when a connection truly lacks operator.read. Co-authored-by: Val Alexander <[email protected]> * build: prepare 2026.3.23 * fix(agents): prefer runtime snapshot for skill secrets * docs(changelog): note skill secretref runtime fix * fix(memory): bootstrap lancedb runtime on demand (openclaw#53111) Bootstrap LanceDB into plugin runtime state on first use for packaged/global installs, keep @lancedb/lancedb plugin-local, and add regression coverage for bundled, cached, retry, and Nix fail-fast runtime paths. Co-authored-by: Val Alexander <[email protected]> * build: finalize 2026.3.23 release * release: upload macos preflight artifacts (openclaw#53105) * release: upload macos preflight artifacts * release: speed up macos preflight * release: use xlarge macos runner * release: skip dmg path in macos preflight * fix(subagents): recheck timed-out announce waits (openclaw#53127) Recheck timed-out subagent announce waits against the latest runtime snapshot before announcing timeout, and keep that recheck best-effort so transient gateway failures do not suppress the announcement. Co-authored-by: Val Alexander <[email protected]> * docs(feishu): replace botName with name in config examples (openclaw#52753) Merged via squash. Prepared head SHA: 5237726 Co-authored-by: haroldfabla2-hue <[email protected]> Co-authored-by: altaywtf <[email protected]> Reviewed-by: @altaywtf * fix(plugins): accept clawhub uninstall specs * test(auth): align device scope expectations (openclaw#53151) * fix: prevent delivery-mirror re-delivery and raise Slack chunk limit (openclaw#45489) Merged via squash. Prepared head SHA: c7664c7 Co-authored-by: theo674 <[email protected]> Co-authored-by: altaywtf <[email protected]> Reviewed-by: @altaywtf * Infra: tighten shell-wrapper positional-argv allowlist matching (openclaw#53133) * Infra: tighten shell carrier allowlist matching * fix(security): tighten shell carrier allowlist matcher * fix: generalize api_error detection for fallback model triggering (openclaw#49611) Co-authored-by: Ayush Ojha <[email protected]> Co-authored-by: altaywtf <[email protected]> * feat(modelstudio): add standard (pay-as-you-go) DashScope endpoints for Qwen (openclaw#43878) Add Standard API Key auth methods for China (dashscope.aliyuncs.com) and Global/Intl (dashscope-intl.aliyuncs.com) pay-as-you-go endpoints alongside the existing Coding Plan (subscription) endpoints. Also updates group label to 'Qwen (Alibaba Cloud Model Studio)' and fixes glm-4.7 -> glm-5 in Coding Plan note messages. Co-authored-by: wenmeng zhou <[email protected]> * Release: privatize macOS publish flow (openclaw#53166) * fix(diagnostics): redact credentials from cache-trace diagnostic output Refs openclaw#53103 * Release: document manual macOS asset upload (openclaw#53178) * Release: document manual macOS asset upload * Release: document macOS smoke-test mode * docs(changelog): reorder release highlights * test(whatsapp): stabilize login coverage in shared workers * test(whatsapp): preserve session exports in login coverage * test(whatsapp): preserve media test module exports * test(whatsapp): preserve harness session exports * fix(ci): stabilize whatsapp extension checks * test: make update-cli checkout path assertion platform-safe * fix(auth): prevent stale auth store reverts (openclaw#53211) * Doctor: prune stale plugin allowlist and entry refs (openclaw#53187) Signed-off-by: sallyom <[email protected]> * test: stabilize test isolation * test: update command coverage * test: expand gemini live transcript stripping * test: fix update-cli default path assertion * chore(sre:PLA-920): adopt upstream sync changes * fix(sre:PLA-920): align branch with adopted upstream tree * build(sre:PLA-920): refresh dist artifacts * test(sre:PLA-920): align incident-format expectations --------- Signed-off-by: sallyom <[email protected]> Co-authored-by: Vincent Koc <[email protected]> Co-authored-by: Peter Steinberger <[email protected]> Co-authored-by: Rick_Xu <[email protected]> Co-authored-by: rcrick <[email protected]> Co-authored-by: frankekn <[email protected]> Co-authored-by: oliviareid-svg <[email protected]> Co-authored-by: oliviareid-svg <[email protected]> Co-authored-by: Frank <[email protected]> Co-authored-by: scoootscooob <[email protected]> Co-authored-by: ruochen <[email protected]> Co-authored-by: Onur Solmaz <[email protected]> Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: Frank Yang <[email protected]> Co-authored-by: artwalker <[email protected]> Co-authored-by: RichardCao <[email protected]> Co-authored-by: create <[email protected]> Co-authored-by: RichardCao <[email protected]> Co-authored-by: liuyang <[email protected]> Co-authored-by: Ayaan Zaidi <[email protected]> Co-authored-by: Matt Van Horn <[email protected]> Co-authored-by: Penchan <[email protected]> Co-authored-by: Penchan <[email protected]> Co-authored-by: Julia Bush <[email protected]> Co-authored-by: Bakhtier Sizhaev <[email protected]> Co-authored-by: Бахтиер Сижаев <[email protected]> Co-authored-by: wangchunyue <[email protected]> Co-authored-by: Tak Hoffman <[email protected]> Co-authored-by: evann <[email protected]> Co-authored-by: Robin Waslander <[email protected]> Co-authored-by: Sathvik Veerapaneni <[email protected]> Co-authored-by: Nimrod Gutman <[email protected]> Co-authored-by: Luke <[email protected]> Co-authored-by: scoootscooob <[email protected]> Co-authored-by: Jamil Zakirov <[email protected]> Co-authored-by: TheRipper <[email protected]> Co-authored-by: Quinn H. <[email protected]> Co-authored-by: Ubuntu <[email protected]> Co-authored-by: Val Alexander <[email protected]> Co-authored-by: betoblair <[email protected]> Co-authored-by: haroldfabla2-hue <[email protected]> Co-authored-by: altaywtf <[email protected]> Co-authored-by: Altay <[email protected]> Co-authored-by: theo674 <[email protected]> Co-authored-by: theo674 <[email protected]> Co-authored-by: Ayush Ojha <[email protected]> Co-authored-by: Ayush Ojha <[email protected]> Co-authored-by: George Zhang <[email protected]> Co-authored-by: wenmeng zhou <[email protected]> Co-authored-by: Onur <[email protected]> Co-authored-by: Sally O'Malley <[email protected]>
* fix(clawhub): resolve auth token for skill browsing * docs(changelog): note clawhub skill auth fix (cherry picked from commit 071de38)
Summary
Testing
NODENV_VERSION=24.13.0 pnpm test -- src/infra/clawhub.test.tsNODENV_VERSION=24.13.0 pnpm test -- src/agents/skills-clawhub.test.tsNODENV_VERSION=24.13.0 pnpm buildFixes #52949