Skip to content

fix(cli): keep channel status checks off plugin runtimes#69479

Merged
gumadeiras merged 31 commits intomainfrom
codex/fix-channel-status-startup-regression
Apr 21, 2026
Merged

fix(cli): keep channel status checks off plugin runtimes#69479
gumadeiras merged 31 commits intomainfrom
codex/fix-channel-status-startup-regression

Conversation

@gumadeiras
Copy link
Copy Markdown
Member

@gumadeiras gumadeiras commented Apr 20, 2026

Summary

  • Problem: read-only CLI status paths regressed after bundled plugin runtime deps moved into extensions; channel/status/doctor paths could import full plugin runtimes just to inspect Telegram, Slack, or Discord config.
  • Why it matters: issue [Bug]: Regression in 2026.4.15: status/doctor/channels commands become much slower when Telegram is configured #69042 reports cold command latency spikes when those channels are configured.
  • What changed: added read-only channel plugin metadata, split Telegram/Slack/Discord security/status helpers out of runtime-heavy channel entrypoints, kept status/health/channels status/channels list/doctor on config-only paths, and made provider usage auth skip plugin auth when there is no direct credential source.
  • What did NOT change: deep/probe/runtime paths still load runtime adapters when the command actually needs live provider or channel behavior.

Change Type (select all)

  • Bug fix
  • Refactor required for the fix

Scope (select all touched areas)

  • Auth / tokens
  • Integrations
  • API / contracts
  • UI / DX

Linked Issue/PR

Root Cause (if applicable)

  • Root cause: fix(plugins): localize bundled runtime deps to extensions #67099 / c727388f937ffc9128ba4e4d2ae37d4c72487bc1 moved bundled runtime dependencies under extension runtime entrypoints. Several read-only commands still reached APIs that resolve the runtime plugin registry, so they paid the full extension import cost even when only config/security/status metadata was needed.
  • Missing detection / guardrail: tests covered command output, but did not assert that status/list/doctor cold paths avoid plugin runtime preloads.
  • Contributing context: channels list also fetched usage by default; with no usage credentials, that path still tried plugin-owned usage auth and loaded provider runtimes before returning no usage rows.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
  • Target test or file: command startup policy, status scan, channels status/list, provider usage auth, doctor auth/memory/workspace tests, and Slack/Discord security helper tests.
  • Scenario the test should lock in: read-only channel/status paths inspect configured Telegram/Slack/Discord accounts without loading full plugin runtimes.
  • Why this is the smallest reliable guardrail: these tests sit at the command/plugin seam where the regression entered.

User-visible / Behavior Changes

  • channels list no longer loads external plugin-synced auth profiles on the no-runtime read-only path; local auth profiles are still listed.
  • Usage rows are unchanged when a direct usage credential source exists. With no env/config/profile credential source, channels list now returns an empty usage summary without loading usage provider plugins.

Diagram (if applicable)

Before:
status/channels list -> configured channel/provider check -> runtime plugin registry -> all plugin runtimes

After:
status/channels list -> read-only metadata/config/security helpers -> output
                         live/deep/probe paths -> runtime plugin registry when needed

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? Yes
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: secret resolution is narrowed for read-only commands. Runtime/deep commands still resolve secrets through existing paths; read-only output preserves token-source/configured status without materializing provider runtimes.

Repro + Verification

Environment

  • OS: macOS 15.7.3 arm64
  • Runtime/container: Node 24.14.1, local repo build
  • Integration/channel: Telegram, Slack, Discord fake env-backed configs
  • Relevant config: temp HOME with one enabled channel account and dummy env token values

Steps

  1. Build: pnpm build
  2. Profile: run OPENCLAW_PLUGIN_LOAD_PROFILE=1 ./openclaw.mjs <command> against temp Telegram config.
  3. Benchmark: /tmp/openclaw-issue-bench.sh /Users/gumadeiras/openclaw <telegram|slack|discord> 1

Expected

  • Read-only commands do not emit full plugin-load profile lines.
  • Issue commands improve versus first-bad cold command timings.

Actual

  • status, doctor --non-interactive, health --verbose, channels list, and channels status emitted plugin_load_lines=0 with Telegram config.
  • health --verbose exits 1 in the temp benchmark because the gateway is not configured/running in that temp HOME; it still stays off plugin runtimes.

Evidence

  • Perf numbers
  • Trace/log snippets

First-bad commit re-measured for this PR update: c727388f937ffc9128ba4e4d2ae37d4c72487bc1.
Current PR head: 26f89ecf59ccd3c5ab2cc2252befec71f0023a64.
Benchmark command: /tmp/openclaw-issue-bench.sh <repo> <telegram|slack|discord> 1; single cold sample per channel/command after pnpm build on both worktrees.

Channel Command First bad c727 PR head 26f89ec Delta
Telegram status 26.163s 12.829s 51.0% faster
Telegram doctor --non-interactive 20.319s 26.472s 30.3% slower
Telegram health --verbose 15.311s 0.839s 94.5% faster
Telegram channels list 22.394s 8.438s 62.3% faster
Telegram channels status 22.298s 8.195s 63.2% faster
Slack status 18.075s 9.370s 48.2% faster
Slack doctor --non-interactive 18.514s 22.317s 20.5% slower
Slack health --verbose 15.161s 0.652s 95.7% faster
Slack channels list 21.427s 8.466s 60.5% faster
Slack channels status 21.375s 8.163s 61.8% faster
Discord status 18.074s 9.489s 47.5% faster
Discord doctor --non-interactive 18.613s 22.194s 19.2% slower
Discord health --verbose 14.285s 0.597s 95.8% faster
Discord channels list 20.498s 8.339s 59.3% faster
Discord channels status 20.104s 8.256s 58.9% faster

Notes:

  • The latest run validates timing gains for status, health --verbose, channels list, and channels status across Telegram, Slack, and Discord.
  • doctor --non-interactive no longer loads full plugin runtimes, but this run is slower because remaining non-plugin doctor work dominates.
  • health --verbose exits 1 in the temp benchmark because the gateway is not configured/running in that temp HOME; it still stays off plugin runtimes.

Human Verification (required)

  • Verified scenarios:
  • Edge cases checked: env-backed channel secrets, no usage credential source, status JSON/read-only output, doctor with no auth profile store.
  • What I did not verify: live Telegram/Slack/Discord API calls; this PR intentionally avoids live runtime probes on read-only paths.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: read-only helpers can drift from runtime channel implementations.
    • Mitigation: shared security helpers live in each owning extension and are covered by extension tests.
  • Risk: provider usage auth skip could hide usage rows when credentials only exist through plugin-synced external profiles and no local auth/profile/env source exists.
    • Mitigation: direct env/config/profile sources still load usage as before; no-credential path previously produced no rows after expensive runtime loading.

Copilot AI review requested due to automatic review settings April 20, 2026 22:16
@gumadeiras gumadeiras requested a review from a team as a code owner April 20, 2026 22:16
@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot Bot commented Apr 20, 2026

🔒 Aisle Security Analysis

We found 2 potential security issue(s) in this PR:

# Severity Title
1 🟠 High Secret target scoping bypass via wildcard/dot characters in channel/plugin IDs
2 🟡 Medium Ambient environment variable names can mark external channels as "configured" and trigger plugin loading on read-only paths
1. 🟠 Secret target scoping bypass via wildcard/dot characters in channel/plugin IDs
Property Value
Severity High
CWE CWE-284
Location src/cli/command-secret-targets.ts:77-98

Description

getConfiguredChannelSecretTargetIds() trusts secretTargetRegistryEntries from read-only (including setup-only external) channel plugins and uses a string prefix check to enforce scoping.

Because pathPattern/refPathPattern are later interpreted as dot-path patterns with special tokens (e.g., * wildcard, [] array) via parseDotPath() / parsePathPattern(), an attacker-controlled plugin.id/channel id containing special characters can change the meaning of the “scoped” prefix:

  • If a plugin/channel id is *, the allowed prefix becomes channels.*.
    • The check entry.pathPattern.startsWith("channels.*.") passes.
    • But parsePathPattern("channels.*.foo") treats * as a wildcard segment, so discovery expands across all channels.
  • If a plugin/channel id contains ., the prefix channels.<id>. no longer corresponds to a single top-level channels[<id>] key because dot-path parsing splits on ., potentially pointing at nested objects under other channels.

This can cause status/audit/secret discovery flows that rely on these “scoped” ids to enumerate and resolve SecretRefs outside the intended channel boundary, leading to unintended secret access or disclosure.

Vulnerable code:

const allowedPrefix = `channels.${channelId}.`;
return (
  params.entry.id.startsWith(allowedPrefix) &&
  params.entry.configFile === "openclaw.json" &&
  typeof params.entry.pathPattern === "string" &&
  params.entry.pathPattern.startsWith(allowedPrefix) &&
  (params.entry.refPathPattern === undefined ||
    params.entry.refPathPattern.startsWith(allowedPrefix))
);

Recommendation

Treat the channel/plugin id as a single literal path segment and prevent it from being interpreted as pattern syntax.

Recommended defenses (do both):

  1. Validate channel ids used for scoping (and/or plugin ids when they are reused as channel ids) to only allow safe characters, e.g. ^[a-z0-9][a-z0-9_-]*$ (no ., *, [, ], whitespace).

  2. Enforce scoping by parsing and comparing path segments/tokens, not raw string prefixes. For example:

import { parseDotPath } from "../secrets/shared.js";

function isScopedToChannel(pathPattern: string, channelId: string): boolean {
  const segs = parseDotPath(pathPattern);// Require exact literal segments: ["channels", channelId, ...]
  return segs.length >= 3 && segs[0] === "channels" && segs[1] === channelId;
}

function isScopedChannelSecretTargetEntry({ entry, pluginChannelId }: { entry: ...; pluginChannelId: string }) {
  const channelId = normalizeOptionalString(pluginChannelId);
  if (!channelId) return false;
  if (entry.configFile !== "openclaw.json") return false;
  if (typeof entry.pathPattern !== "string") return false;
  if (!isScopedToChannel(entry.id, channelId)) return false;
  if (!isScopedToChannel(entry.pathPattern, channelId)) return false;
  if (entry.refPathPattern !== undefined && !isScopedToChannel(entry.refPathPattern, channelId)) return false;
  return true;
}

This prevents * / [] / . in ids from altering the matcher semantics.

2. 🟡 Ambient environment variable names can mark external channels as "configured" and trigger plugin loading on read-only paths
Property Value
Severity Medium
CWE CWE-927
Location src/plugins/channel-plugin-ids.ts:69-76

Description

External channel plugins can declare channelEnvVars in their manifest, and any non-empty matching environment variable will cause the host to treat the corresponding channel as configured.

Impact:

  • Input: plugin-controlled manifest field channelEnvVars[channelId] (from external plugin manifests)
  • Condition: hasNonEmptyEnvValue() treats many generic env var names as valid triggers (only a small blacklist is blocked)
  • Effect: channel is considered configured and can influence read-only/status flows that resolve/load setup-only channel plugins (e.g., src/channels/plugins/read-only.ts calls loadOpenClawPlugins(...) for missing configured channels).

This is risky because a malicious/buggy but explicitly trusted/allowed plugin can select overly-generic names (e.g., TOKEN, KEY, PASSWORD, AWS_REGION, etc.) that are often set in CI shells, causing unexpected plugin loading/execution even when the user did not intend to configure that channel.

Vulnerable code:

function hasNonEmptyEnvValue(env: NodeJS.ProcessEnv, key: string): boolean {
  if (!isSafeChannelEnvVarTriggerName(key)) {
    return false;
  }
  const trimmed = key.trim();
  const value = env[trimmed] ?? env[trimmed.toUpperCase()];
  return typeof value === "string" && value.trim().length > 0;
}

and the safety check is blacklist-based:

return /^[A-Z][A-Z0-9_]*$/.test(normalized) && !UNSAFE_CHANNEL_ENV_VAR_TRIGGER_NAMES.has(normalized)

which still permits many common ambient names.

Recommendation

Make env-var-based configuration triggers opt-in and strongly namespaced, rather than relying on a small blacklist.

Suggested hardening options (combine as appropriate):

  1. Require a prefix (recommended): only treat env vars as triggers if they match OPENCLAW_... or a plugin/channel-specific prefix.
export function isSafeChannelEnvVarTriggerName(key: string): boolean {
  const normalized = key.trim().toUpperCase();
  if (!/^OPENCLAW_[A-Z0-9_]+$/.test(normalized)) return false;
  return true;
}
  1. Require explicit user configuration in openclaw config mapping channelId -> envVar names, and ignore manifest-provided env var triggers by default.

  2. If manifest triggers are kept, replace blacklist with an allowlist of acceptable patterns (e.g., ^<PLUGINID>_[A-Z0-9_]+$) and consider rejecting extremely short/generic names.

Also consider setting loadModules: false for read-only/status discovery flows to avoid executing plugin module top-level code during mere "configured" detection.


Analyzed PR: #69479 at commit 63f6e41

Last updated on: 2026-04-21T17:56:50Z

@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord channel: slack Channel integration: slack channel: telegram Channel integration: telegram cli CLI command changes commands Command implementations size: XL maintainer Maintainer-authored PR labels Apr 20, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This PR fixes a cold-start latency regression (#69042) where read-only CLI commands (status, channels list, channels status, doctor, health) were loading full plugin runtimes for every configured Telegram/Slack/Discord channel. The fix extracts security/status helpers out of runtime-heavy channel entrypoints into lightweight security.ts modules, adds a listReadOnlyChannelPluginsForConfig helper, and makes loadProviderUsageSummary skip plugin-owned usage auth when no direct credential source exists.

Confidence Score: 5/5

Safe to merge; all remaining findings are P2 style/edge-case observations that do not affect correctness on the targeted paths.

The architectural split (runtime vs. read-only security adapters) is sound, the latency numbers are well-evidenced, and the three inline findings are either a minor type-safety style gap (missing satisfies on Telegram) or unlikely edge-case observations with no impact on the common single-provider case. No P0/P1 issues found.

extensions/telegram/src/security.ts (missing satisfies guard); src/security/audit.ts (sourceConfig vs autoEnabled.config mismatch in channel ID deletion); src/infra/provider-usage.auth.ts (per-provider vs. global allowAuthProfileStore gate)

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/infra/provider-usage.auth.ts
Line: 240-260

Comment:
**`hasDirectCredentialSource` is evaluated across all providers jointly, not per-provider**

The check gates the single `allowAuthProfileStore` flag for every provider in the loop. If `providers = ["openai", "anthropic"]` and only `"openai"` has a direct env/config credential, `hasDirectCredentialSource` is `true`, `allowAuthProfileStore` becomes `true`, and plugin auth is attempted for `"anthropic"` even though it has no direct credential source. The PR description says "skip plugin auth when there is no direct credential source", but the skip only applies when *none* of the providers have a direct source.

This is benign for the targeted use case (a single usage provider is most common), but if two usage providers are configured and only one has credentials, the read-only path will still load the plugin runtime for the second provider.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/security/audit.ts
Line: 358-365

Comment:
**Channel ID removal uses `sourceConfig`; `requestedPluginIds` is built from `autoEnabled.config`**

`requestedPluginIds` is populated from `autoEnabled.config` (which may diverge from `sourceConfig` after `applyPluginAutoEnable` merges auto-enable overrides), but the IDs to delete are derived from `listPotentialConfiguredChannelIds(context.sourceConfig, …)`. In theory, a channel that is auto-enabled at the `autoEnabled.config` level but absent from `sourceConfig` would survive the deletion and still trigger a full plugin metadata registry load for that channel.

Practically this is an unlikely edge case, but since the entire PR targets latency on read-only paths, it's worth verifying that `listPotentialConfiguredChannelIds` is called against the same config object that seeded `requestedPluginIds` (i.e., `autoEnabled.config`).

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/telegram/src/security.ts
Line: 28-36

Comment:
**Missing `satisfies` type guard on Telegram security adapter**

`telegramSecurityAdapter` is exported without the `satisfies NonNullable<ChannelPlugin<ResolvedTelegramAccount>["security"]>` constraint that the Slack (`extensions/slack/src/security.ts`) and Discord (`extensions/discord/src/security.ts`) adapters both use. If the `ChannelPlugin["security"]` contract gains a required field, this adapter will silently pass TypeScript checking while the others immediately fail, hiding the regression from the read-only path.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: add channel read-only security adap..." | Re-trigger Greptile

Comment thread src/infra/provider-usage.auth.ts
Comment thread src/security/audit.ts
Comment thread extensions/telegram/src/security.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6a45d1d06f

ℹ️ 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".

Comment thread src/channels/plugins/read-only.ts Outdated
Comment thread src/cli/command-secret-targets.ts Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a CLI cold-start regression by keeping read-only status/doctor/health/channels paths on config-only + bundled metadata surfaces, avoiding full bundled channel/provider runtime imports when users have Telegram/Slack/Discord configured.

Changes:

  • Introduces read-only channel plugin listing and routes multiple read-only commands through config/metadata-based helpers instead of runtime-heavy plugin entrypoints.
  • Adds a snapshot-based plugin compatibility notice path for status/config validation/doctor workspace outputs.
  • Narrows provider-usage auth so channels list can skip plugin-based usage auth when no direct credential source exists, plus adds guardrail tests to lock in “no plugin preload” behavior.

Reviewed changes

Copilot reviewed 67 out of 67 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/security/audit.ts Avoids loading plugin audit collectors for configured channels when channel security plugins are supplied directly.
src/plugins/status.ts Adds compatibility notices based on snapshot report (no runtime module loading).
src/infra/provider-usage.load.ts Plumbs option to skip plugin usage auth without credentials.
src/infra/provider-usage.auth.ts Implements “skip plugin auth without credential source” behavior and config/env key checks.
src/infra/provider-usage.auth.plugin.test.ts Tests plugin-boundary behavior for usage auth skipping.
src/infra/provider-usage.auth.normalizes-keys.test.ts Updates mocks to support auth store source detection.
src/infra/channel-summary.ts Switches to read-only channel plugin listing for summaries.
src/flows/doctor-health-contributions.ts Reduces runtime repair/recall work in non-deep / non-fix doctor flows.
src/commands/status.summary.ts Adds flag to disable channel summary imports/processing.
src/commands/status.summary.test.ts Tests “includeChannelSummary: false” behavior.
src/commands/status.scan.ts Uses snapshot-based plugin compatibility notices.
src/commands/status.scan.test.ts Updates expectations to ensure no plugin registry preload for status JSON.
src/commands/status.scan.test-helpers.ts Extends status plugin status module mock surface.
src/commands/status.scan.fast-json.ts Removes configured-channel plugin preload; disables channel summary on lean JSON path.
src/commands/status.scan.fast-json.test.ts Updates tests to assert no plugin preload and no channel summary on fast JSON.
src/commands/status.scan-overview.ts Limits secret target discovery to configured channels for status.
src/commands/status.scan-execute.ts Threads summary policy (includeChannelSummary) into execution.
src/commands/status.scan-execute.test.ts Updates expectations for summary policy plumbing.
src/commands/status.link-channel.ts Uses read-only channel plugin listing.
src/commands/status.link-channel.test.ts Updates mocks for read-only channel plugin listing.
src/commands/status-runtime-shared.ts Passes read-only channel plugins into security audit to avoid runtime loads.
src/commands/status-runtime-shared.test.ts Asserts plugins passed into security audit call.
src/commands/status-json.test.ts Updates security audit invocation expectations.
src/commands/status-all/channels.ts Switches channels table building to read-only plugin listing.
src/commands/health.ts Uses read-only channel plugin listing; avoids plugin preload dependencies.
src/commands/health.command.coverage.test.ts Updates coverage expectation for web self-id logging.
src/commands/doctor-workspace-status.ts Uses snapshot plugin report instead of diagnostics report.
src/commands/doctor-workspace-status.test.ts Updates mocks for snapshot plugin report usage.
src/commands/doctor-memory-search.ts Moves some memory checks to config-only metadata; reduces runtime dependence in checks.
src/commands/doctor-memory-search.test.ts Updates tests for new config-only/provider probing behavior.
src/commands/doctor-claude-cli.ts Avoids loading auth profile store when no config/store signals exist.
src/commands/doctor-auth.ts Skips external auth profile resolution when no auth sources exist.
src/commands/doctor-auth.profile-health.test.ts New test covering early-return when no auth sources exist.
src/commands/doctor-auth.deprecated-cli-profiles.test.ts Adds test ensuring provider loading is skipped when no legacy OAuth profiles exist.
src/commands/doctor-auth-legacy-oauth.ts Avoids provider loading when config/store contain no relevant OAuth entries.
src/commands/config-validation.ts Uses snapshot-based plugin compatibility notices during config validation.
src/commands/config-validation.test.ts Updates mocks to use snapshot compatibility notices.
src/commands/channels/status.ts Keeps JSON fallback config-only; narrows secret targets to configured channels.
src/commands/channels/status-config-format.ts Uses read-only channel plugin listing for config-only formatting.
src/commands/channels/shared.ts Uses loaded/setup plugin surfaces to label channels without runtime loads where possible.
src/commands/channels/list.ts Uses read-only channel plugin listing; loads auth store without external profiles; skips plugin usage auth when no creds.
src/commands/channels.status.command-flow.test.ts Adds mocks/tests for config-only JSON fallback behavior.
src/commands/channels.list.auth-profiles.test.ts Updates to assert local-only auth profile listing without external profile loading.
src/commands/channels.config-only-status-output.test.ts Updates mocks to support read-only channel plugin listing.
src/cli/program/routes.test.ts Adds routed coverage for channels list/status and asserts no plugin preload.
src/cli/program/routed-command-definitions.ts Adds routed command definitions for channels list/status.
src/cli/program/route-args.ts Adds argv parsers for channels list/status routed commands.
src/cli/program/preaction.test.ts Updates preaction expectations: no plugin registry preload for status.
src/cli/command-startup-policy.test.ts Updates policy expectations: status/health/channels list/status should not load plugins.
src/cli/command-secret-targets.ts Adds configured-channel secret target selection via bundled channel contract metadata.
src/cli/command-secret-targets.import.test.ts Adds test ensuring configured-channel status targets resolve without touching full registry.
src/cli/command-path-policy.test.ts Updates CLI command path policy: status never loads plugins; adds channels list/status policies.
src/cli/command-catalog.ts Adds channels list/status to CLI catalog; changes status/health to never preload plugins.
src/cli/channels-cli.ts Switches channels list/status actions to direct imports (avoids heavier loader).
src/channels/plugins/read-only.ts New helper to list channel plugins for read-only paths based on config/configured channels.
extensions/telegram/src/shared.ts Exposes security adapter on setup/base surface.
extensions/telegram/src/security.ts New shared Telegram security adapter module.
extensions/telegram/src/channel.ts Uses shared Telegram security adapter; removes inline security collectors.
extensions/slack/src/shared.ts Exposes security adapter on setup/base surface.
extensions/slack/src/shared.test.ts Adds test ensuring security surface is exposed.
extensions/slack/src/security.ts New shared Slack security adapter module.
extensions/slack/src/channel.ts Uses shared Slack security adapter; removes inline security collectors.
extensions/discord/src/shared.ts Exposes security adapter on setup/base surface.
extensions/discord/src/shared.test.ts Adds test ensuring security surface is exposed.
extensions/discord/src/security.ts New shared Discord security adapter module with lazy audit import.
extensions/discord/src/channel.ts Uses shared Discord security adapter; removes inline security collectors.
CHANGELOG.md Documents the CLI cold-path performance fix for configured Telegram/Slack/Discord.

Comment thread src/channels/plugins/read-only.ts Outdated
@gumadeiras gumadeiras self-assigned this Apr 20, 2026
@openclaw-barnacle openclaw-barnacle Bot added the docs Improvements or additions to documentation label Apr 20, 2026
@gumadeiras gumadeiras force-pushed the codex/fix-channel-status-startup-regression branch from 8f57b21 to fe7f3aa Compare April 20, 2026 23:47
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fe7f3aa834

ℹ️ 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".

Comment thread src/security/audit.ts Outdated
@gumadeiras
Copy link
Copy Markdown
Member Author

Check triage update:

  • Greptile provider-auth comment was valid. Fixed in e6a1565 so skipPluginAuthWithoutCredentialSource is evaluated per usage provider, with regression coverage.
  • Codex audit-scope comment was valid. Fixed in e6a1565 by pruning configured channel owner plugin IDs, routing workspace discovery into audit/plugin metadata paths, and covering the read-only audit scope.
  • Aisle security finding is rejected as a security issue after checking SECURITY.md. OpenClaw’s policy explicitly treats installed/enabled plugins as part of the gateway TCB; reports must show a boundary bypass such as unauthenticated plugin load, allowlist/policy bypass, or sandbox/path-safety bypass. The read-only setup path only loads trusted configured/discoverable channel owner setup entries through the existing plugin trust policy, so this is not CWE-94 in OpenClaw’s documented model.

Local verification run:

  • pnpm test src/infra/provider-usage.auth.plugin.test.ts src/plugins/channel-plugin-ids.test.ts src/security/audit-plugin-readonly-scope.test.ts src/channels/plugins/read-only.test.ts src/plugins/runtime/runtime-registry-loader.test.ts
  • pnpm tsgo

Also attempted the repo changed-scope pre-commit gate. Typecheck/lint/import-cycle/guards passed, but the broad infra test lane failed in unrelated git-env tests (src/infra/git-commit.test.ts, src/infra/host-env-security.test.ts, src/infra/run-node.test.ts, src/infra/update-check.test.ts). I did not chase those unrelated failures.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 18e04abb0a

ℹ️ 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".

Comment thread src/channels/plugins/read-only.ts Outdated
@gumadeiras
Copy link
Copy Markdown
Member Author

Check triage update for the latest bot comments:

  • The persisted-auth read-only discovery thread was valid. Fixed in 4a4f38f by restoring the helper default to include persisted auth state unless callers explicitly opt out. Existing config/env-only callers still pass includePersistedAuthState: false.
  • Aisle item 1 was valid as a hardening/correctness gap, though overstated as a security boundary issue. Fixed in 4a4f38f by accepting external setup plugins only when their exported channel id is one of the missing configured ids, and by preventing external setup entries from overwriting an existing channel id. Added a spoofed-channel regression test.
  • Aisle item 2 is rejected as a security issue after checking SECURITY.md. Trusted installed/enabled plugins are in the gateway TCB, and setup/install flows may intentionally evaluate trusted plugin code. The read-only status path this PR changes already passes requireSetupEntryForSetupOnlyChannelPlugins: true, so it does not fall back to the full entrypoint.

Verification:

  • pnpm test src/channels/plugins/read-only.test.ts src/cli/command-secret-targets.import.test.ts src/cli/command-secret-targets.test.ts
  • pnpm tsgo:core
  • repo pre-commit changed-scope hook from scripts/committer passed, including core/core-test/extension/extension-test typechecks, lint, import-cycle/guards, changed tests, and test:extensions.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4a4f38f140

ℹ️ 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".

Comment thread src/infra/provider-usage.auth.ts
Comment thread src/commands/doctor-memory-search.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f0f3e6867e

ℹ️ 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".

Comment thread src/infra/provider-usage.auth.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 26f89ecf59

ℹ️ 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".

Comment thread src/infra/provider-usage.auth.ts Outdated
@openclaw-barnacle openclaw-barnacle Bot added the agents Agent runtime and tooling label Apr 21, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5448c88f39

ℹ️ 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".

Comment thread src/commands/status-runtime-shared.ts Outdated
Comment thread src/plugins/channel-plugin-ids.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9fe0e45697

ℹ️ 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".

Comment thread src/channels/plugins/read-only.ts Outdated
Comment thread src/cli/command-secret-targets.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8259a34239

ℹ️ 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".

Comment thread src/infra/provider-usage.auth.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b31ab2cad

ℹ️ 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".

Comment thread src/secrets/channel-env-var-names.ts
@gumadeiras gumadeiras force-pushed the codex/fix-channel-status-startup-regression branch from e8cce7a to 63f6e41 Compare April 21, 2026 17:52
@gumadeiras gumadeiras merged commit 24db09a into main Apr 21, 2026
83 checks passed
@gumadeiras gumadeiras deleted the codex/fix-channel-status-startup-regression branch April 21, 2026 17:53
@gumadeiras
Copy link
Copy Markdown
Member Author

Merged via squash.

Thanks @gumadeiras!

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 63f6e416a9

ℹ️ 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".

Comment thread src/infra/provider-usage.auth.ts
gdibble pushed a commit to gdibble/openclaw that referenced this pull request Apr 21, 2026
)

Merged via squash.

Prepared head SHA: 63f6e41
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
medikoo pushed a commit to medikoo/openclaw that referenced this pull request Apr 24, 2026
)

Merged via squash.

Prepared head SHA: 63f6e41
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
)

Merged via squash.

Prepared head SHA: 63f6e41
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
zhonghe0615 pushed a commit to zhonghe0615/openclaw that referenced this pull request May 7, 2026
)

Merged via squash.

Prepared head SHA: 63f6e41
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
)

Merged via squash.

Prepared head SHA: 63f6e41
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: discord Channel integration: discord channel: slack Channel integration: slack channel: telegram Channel integration: telegram cli CLI command changes commands Command implementations docs Improvements or additions to documentation extensions: minimax maintainer Maintainer-authored PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Regression in 2026.4.15: status/doctor/channels commands become much slower when Telegram is configured

2 participants