Skip to content

!refactor(xai): move x_search config behind plugin boundary#59674

Merged
vincentkoc merged 5 commits into
mainfrom
chore/x-search-plugin-boundary
Apr 2, 2026
Merged

!refactor(xai): move x_search config behind plugin boundary#59674
vincentkoc merged 5 commits into
mainfrom
chore/x-search-plugin-boundary

Conversation

@vincentkoc

Copy link
Copy Markdown
Member

Summary

  • move x_search settings out of core tools.web.x_search.* and into plugin-owned plugins.entries.xai.config.xSearch.*
  • standardize x_search auth on shared xAI web-search auth (plugins.entries.xai.config.webSearch.apiKey / XAI_API_KEY), with legacy tools.web.x_search.apiKey treated as migration compat
  • remove the bespoke core x_search runtime secret/status plumbing and let generic plugin-owned web-search auth resolution carry the runtime path

What changed

  • added plugin-owned xSearch config schema/ui hints in extensions/xai/openclaw.plugin.json
  • rewired extensions/xai/x-search.ts and extensions/xai/web-search.ts to read/write plugin-owned xSearch config
  • added src/config/legacy-x-search.ts and doctor migration wiring for tools.web.x_search.*
  • removed tools.web.x_search.apiKey from core secret target/status handling and runtime-web-tools special cases
  • tightened runtime web-search secret activation so plugin-owned web-search auth resolves even when tools.web.search is absent
  • regenerated config baseline artifacts

Why

x_search execution was already plugin-owned, but config, secret activation, and secret-gateway UX still lived in core. This keeps recreating the same mixed boundary we just cleaned up for web_fetch/Firecrawl. This PR makes the XAI plugin the real owner of x_search settings while keeping a compat window for legacy config.

Compatibility

  • canonical settings path is now plugins.entries.xai.config.xSearch.*
  • canonical auth path for x_search is plugins.entries.xai.config.webSearch.apiKey
  • legacy tools.web.x_search.* is still loadable and migrated by openclaw doctor --fix
  • runtime secret activation also normalizes legacy tools.web.x_search.apiKey into the plugin-owned path before resolution so old SecretRef-based configs keep working during the migration window

Testing

  • pnpm test -- src/secrets/runtime-web-tools.test.ts src/secrets/runtime.test.ts src/config/legacy-x-search.test.ts
  • pnpm test -- extensions/xai/x-search.test.ts extensions/xai/web-search.test.ts extensions/xai/x-search.live.test.ts src/config/legacy-x-search.test.ts src/commands/doctor-legacy-config.migrations.test.ts src/secrets/runtime.test.ts src/secrets/runtime-web-tools.test.ts src/flows/search-setup.test.ts src/config/plugin-auto-enable.test.ts src/cli/command-secret-targets.test.ts src/web-search/runtime.test.ts
  • pnpm tsgo
  • pnpm config:docs:gen
  • node --import tsx scripts/generate-base-config-schema.ts --write
  • pnpm build

AI-assisted. Fully tested on the touched surface.

@vincentkoc vincentkoc self-assigned this Apr 2, 2026
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation cli CLI command changes commands Command implementations size: L maintainer Maintainer-authored PR labels Apr 2, 2026
@vincentkoc vincentkoc marked this pull request as ready for review April 2, 2026 12:49
@vincentkoc vincentkoc requested a review from a team as a code owner April 2, 2026 12:49
@vincentkoc vincentkoc changed the title refactor(xai): move x_search config behind plugin boundary !refactor(xai): move x_search config behind plugin boundary Apr 2, 2026

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

Copy link
Copy Markdown

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: 91f131571c

ℹ️ 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/runtime.ts
Comment thread extensions/xai/x-search.ts
@greptile-apps

greptile-apps Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR moves x_search config out of the core tools.web.x_search.* namespace into the plugin-owned plugins.entries.xai.config.xSearch.* path, standardises auth on the shared plugins.entries.xai.config.webSearch.apiKey / XAI_API_KEY credential, and wires in a doctor migration for legacy configs. The approach mirrors the earlier Firecrawl/web-fetch refactor and is well-tested across the touched surface.

Confidence Score: 5/5

  • Safe to merge; all remaining findings are P2 style issues that do not affect runtime correctness.
  • The PR is structurally sound and fully tested. The previous P0 concern (missing legacy-x-search.ts) is resolved — the file is present in the HEAD commit. The two remaining findings are: (1) two unused variables left over from the refactor in resolveXSearchApiKey, and (2) the doctor migration auto-enabling the xAI plugin without recording it in the changes log. Neither affects runtime behaviour.
  • extensions/xai/x-search.ts (dead variables in resolveXSearchApiKey), src/config/legacy-x-search.ts (silent plugin enable in migration)
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/xai/x-search.ts
Line: 114-118

Comment:
**Dead code: unused variables after refactor**

`sourceXSearchConfig` and `runtimeXSearchConfig` are computed but never referenced in the return expression. The refactor removed the old `readConfiguredSecretString(runtimeXSearchConfig?.apiKey, …)` calls but left the variable assignments behind.

```suggestion
  return (
    resolveFallbackXaiApiKey(params.runtimeConfig) ??
    resolveFallbackXaiApiKey(params.sourceConfig) ??
    readLegacyXSearchApiKey(params.runtimeConfig) ??
    readLegacyXSearchApiKey(params.sourceConfig) ??
    readProviderEnvValue(["XAI_API_KEY"])
  );
```

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/config/legacy-x-search.ts
Line: 82-85

Comment:
**Silent plugin auto-enable not surfaced in changes log**

When the xAI plugin entry did not previously have an `enabled` field, the migration unconditionally sets `entry.enabled = true` but never pushes a corresponding entry into `changes`. Users running `openclaw doctor --fix` with a legacy `tools.web.x_search` config will see the config moved, but will not be told that the xAI plugin was also auto-enabled. Consider adding a change line such as `"Enabled plugins.entries.xai (auto-enabled by x_search migration)."` when `!hadEnabled` so the side effect is visible in the doctor output.

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

Reviews (2): Last reviewed commit: "Merge branch 'main' into chore/x-search-..." | Re-trigger Greptile

Comment thread src/secrets/runtime.ts
@aisle-research-bot

aisle-research-bot Bot commented Apr 2, 2026

Copy link
Copy Markdown

🔒 Aisle Security Analysis

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

# Severity Title
1 🟡 Medium Legacy x_search migration can unintentionally enable xAI code_execution tool via shared API key and forced plugin enablement
1. 🟡 Legacy x_search migration can unintentionally enable xAI code_execution tool via shared API key and forced plugin enablement
Property Value
Severity Medium
CWE CWE-269
Location src/config/legacy-x-search.ts:79-96

Description

migrateLegacyXSearchConfig migrates legacy tools.web.x_search settings into the xAI plugin config and forces plugins.entries.xai.enabled = true when no explicit enabled flag existed.

Because the xAI plugin registers multiple tools (x_search and code_execution) and code_execution is considered enabled whenever an xAI API key is available (unless codeExecution.enabled === false), migrating a legacy x_search API key into plugins.entries.xai.config.webSearch.apiKey can unintentionally activate the higher-risk code_execution tool for users who only configured X search.

Impact:

  • A configuration that previously only enabled legacy x_search can, after migration, end up enabling the xAI plugin broadly.
  • With the migrated API key present, createCodeExecutionTool() returns a live code_execution tool unless it is explicitly disabled.
  • This expands capability surface area (remote sandbox execution) without an explicit user opt-in.

Vulnerable code:

const hadEnabled = entry.enabled !== undefined;
if (!hadEnabled) {
  entry.enabled = true;
}
...
config.webSearch = { apiKey: auth };

Recommendation

Avoid implicitly broad-enabling the plugin or any higher-privilege tools during migration.

Safer options:

  1. Do not set plugins.entries.xai.enabled = true during migration; instead only migrate config, and let existing auto-enable logic decide.
  2. If plugin enablement is required for x_search to work, explicitly disable code execution unless the user had enabled it:
if (!hadEnabled) {
  entry.enabled = true;
}
const config = ensureRecord(entry, "config");// Ensure legacy x_search migration does not also enable code_execution
if (!isRecord(config.codeExecution) || (config.codeExecution as any).enabled === undefined) {
  config.codeExecution = { ...(isRecord(config.codeExecution) ? config.codeExecution : {}), enabled: false };
}// Optionally set xSearch.enabled = true to scope intent
config.xSearch = { ...(isRecord(config.xSearch) ? config.xSearch : {}), enabled: true };
  1. Alternatively, change createCodeExecutionTool() enablement to require explicit opt-in (codeExecution.enabled === true) rather than defaulting to enabled when a key exists.

Analyzed PR: #59674 at commit 5050e17

Last updated on: 2026-04-02T13:39:47Z

@vincentkoc

Copy link
Copy Markdown
Member Author

@greptileai review

@vincentkoc vincentkoc merged commit 3e4de95 into main Apr 2, 2026
9 checks passed
@vincentkoc vincentkoc deleted the chore/x-search-plugin-boundary branch April 2, 2026 13:09

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

Copy link
Copy Markdown

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: 5050e1713d

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

});
return value !== undefined;
});
const searchEnabled = hasConfiguredSearchSurface && search?.enabled !== false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Resolve x_search SecretRefs even when web search is disabled

x_search now reads plugins.entries.xai.config.webSearch.apiKey, but this function only resolves web-search credentials inside if (searchEnabled), and searchEnabled is forced false when tools.web.search.enabled is false. In that configuration, the xAI SecretRef is left unresolved in the runtime snapshot, and createXSearchTool later throws on that unresolved SecretRef (plugins.entries.xai.config.webSearch.apiKey) instead of running x_search; this regresses configs that intentionally disable tools.web.search while keeping x_search enabled via SecretRef-backed auth.

Useful? React with 👍 / 👎.

ngutman pushed a commit that referenced this pull request Apr 3, 2026
* refactor(xai): move x_search config behind plugin boundary

* chore(changelog): note x_search config migration

* fix(xai): include x_search migration helpers
steipete pushed a commit to duncanita/openclaw that referenced this pull request Apr 4, 2026
…#59674)

* refactor(xai): move x_search config behind plugin boundary

* chore(changelog): note x_search config migration

* fix(xai): include x_search migration helpers
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…#59674)

* refactor(xai): move x_search config behind plugin boundary

* chore(changelog): note x_search config migration

* fix(xai): include x_search migration helpers
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…#59674)

* refactor(xai): move x_search config behind plugin boundary

* chore(changelog): note x_search config migration

* fix(xai): include x_search migration helpers
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…#59674)

* refactor(xai): move x_search config behind plugin boundary

* chore(changelog): note x_search config migration

* fix(xai): include x_search migration helpers
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…#59674)

* refactor(xai): move x_search config behind plugin boundary

* chore(changelog): note x_search config migration

* fix(xai): include x_search migration helpers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli CLI command changes commands Command implementations docs Improvements or additions to documentation maintainer Maintainer-authored PR size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant