Skip to content

fix(cli): resolve web command SecretRefs#82819

Merged
steipete merged 6 commits into
mainfrom
fix/cli-web-search-secret-refs
May 17, 2026
Merged

fix(cli): resolve web command SecretRefs#82819
steipete merged 6 commits into
mainfrom
fix/cli-web-search-secret-refs

Conversation

@steipete

@steipete steipete commented May 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Verification

  • codex-review: clean, no actionable findings.
  • node scripts/run-vitest.mjs src/secrets/runtime-command-secrets.test.ts src/cli/command-secret-gateway.test.ts src/cli/command-secret-targets.test.ts src/gateway/server-methods/secrets.test.ts src/cli/capability-cli.test.ts src/cli/command-config-resolution.test.ts
  • TAVILY_API_KEY=resolved-live-proof pnpm exec tsx scripts/repro/cli-web-search-secret-refs-live-proof.mjs
  • pnpm tsgo:core
  • git diff --check
  • Crabbox AWS cbx_aebcfe04e4bc, hydrated by Actions run 25977253055, E2E run run_e442983bbd8d.

Real behavior proof

Behavior addressed: infer web search and infer web fetch now resolve only the selected web provider SecretRefs, including --provider overrides, and leave unrelated plugin secrets inactive.
Real environment tested: local source checkout plus AWS Crabbox cbx_aebcfe04e4bc with live provider keys injected through an allowlisted env profile.
Exact steps or command run after this patch: node scripts/run-vitest.mjs src/secrets/runtime-command-secrets.test.ts src/cli/command-secret-gateway.test.ts src/cli/command-secret-targets.test.ts src/gateway/server-methods/secrets.test.ts src/cli/capability-cli.test.ts src/cli/command-config-resolution.test.ts; TAVILY_API_KEY=resolved-live-proof pnpm exec tsx scripts/repro/cli-web-search-secret-refs-live-proof.mjs; pnpm tsgo:core; git diff --check; pnpm crabbox:run -- --provider aws --id cbx_aebcfe04e4bc --no-sync --env-from-profile /tmp/openclaw-82699-live-web.env --allow-env FIRECRAWL_API_KEY,GEMINI_API_KEY,XAI_API_KEY --script /tmp/openclaw-82699-crabbox-live.sh.
Evidence after fix: local focused suite passed 7 files and 137 tests; live repro converted a Tavily env SecretRef to a string; Crabbox installed and inspected the Firecrawl plugin, DuckDuckGo config and CLI override searches returned results, and Grok, Gemini, and Firecrawl config and CLI override cases reached the expected live provider auth responses with redacted key presence.
Observed result after fix: selected web provider credentials are resolved for command execution, unrelated voice-call/Twilio SecretRefs remain inactive, and legacy Firecrawl fetch refs remain covered.
What was not tested: valid paid-provider success for Grok, Gemini, or Firecrawl because the available live keys currently return provider auth errors; those errors still prove the selected SecretRefs were resolved and used.

Fixes #82621.
Supersedes #82699.

@steipete steipete requested a review from a team as a code owner May 17, 2026 00:59
@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui gateway Gateway runtime cli CLI command changes scripts Repository scripts size: XL maintainer Maintainer-authored PR labels May 17, 2026
@clawsweeper

clawsweeper Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge.

Summary
The branch routes CLI web search/fetch SecretRef resolution through provider-aware command and gateway paths, adds provider override protocol support, preserves legacy Firecrawl fetch credentials, and adds focused tests/repro coverage.

Reproducibility: yes. for review purposes: configure a non-bundled web provider with a plugin-scoped webSearch/webFetch SecretRef and select it with infer web ... --provider. Source inspection shows the PR's override matchers use bundled-only owner lookup, so that selected path is treated as inactive instead of returned.

Real behavior proof
Override: A maintainer applied proof: override for this PR.

Next step before merge
The remaining blockers are narrow code repairs in the PR branch: remove bundled-only provider-owner matching from the active-snapshot and local-fallback override paths, then rerun the focused validation.

Security
Cleared: No concrete security or supply-chain regression remains in the latest diff; the prior API-key prefix disclosure in the repro script was removed.

Review findings

  • [P1] Resolve active-snapshot override owners across plugin origins — src/secrets/runtime-command-secrets.ts:122-126
  • [P1] Resolve local-fallback override owners across plugin origins — src/cli/command-secret-gateway.ts:193-197
Review details

Best possible solution:

Keep the provider-aware command SecretRef design, but align every selected-provider owner check with the registry-aware, origin-agnostic lookup used by command target selection before landing.

Do we have a high-confidence way to reproduce the issue?

Yes for review purposes: configure a non-bundled web provider with a plugin-scoped webSearch/webFetch SecretRef and select it with infer web ... --provider. Source inspection shows the PR's override matchers use bundled-only owner lookup, so that selected path is treated as inactive instead of returned.

Is this the best way to solve the issue?

No: the overall provider-aware approach is the right boundary, and the latest head fixed the secret-prefix repro leak, but the override owner checks still need to match current main's origin-agnostic registry contract.

Full review comments:

  • [P1] Resolve active-snapshot override owners across plugin origins — src/secrets/runtime-command-secrets.ts:122-126
    getWebSearchCommandSecretTargets can select non-bundled provider plugin paths because current main uses origin-agnostic owner lookup, but this new active-snapshot override check asks for origin: "bundled". A selected installed provider then has its plugin-scoped SecretRef restored to inactive/unresolved instead of returned as the chosen credential assignment.
    Confidence: 0.91
  • [P1] Resolve local-fallback override owners across plugin origins — src/cli/command-secret-gateway.ts:193-197
    The gateway-unavailable local fallback repeats the bundled-only owner filter. If secrets.resolve is unavailable and the user selects a non-bundled web provider with --provider, the selected plugin credential path is classified inactive and skipped even though command target selection allowed it.
    Confidence: 0.9

Overall correctness: patch is incorrect
Overall confidence: 0.91

Acceptance criteria:

  • node scripts/run-vitest.mjs src/secrets/runtime-command-secrets.test.ts src/cli/command-secret-gateway.test.ts src/cli/command-secret-targets.test.ts src/gateway/server-methods/secrets.test.ts src/cli/capability-cli.test.ts src/cli/command-config-resolution.test.ts
  • TAVILY_API_KEY=resolved-live-proof pnpm exec tsx scripts/repro/cli-web-search-secret-refs-live-proof.mjs
  • pnpm tsgo:core
  • git diff --check

What I checked:

  • Live PR metadata: Unauthenticated GitHub API shows the PR is open at head 44fb025 with labels including maintainer and proof: override. (44fb025ade5d)
  • Current main target selection is origin-agnostic: Current main resolves the selected web provider owner without passing an origin filter, so command target selection can choose installed/non-bundled provider plugin credential paths. (src/cli/command-secret-targets.ts:345, 2a7f9f354644)
  • Registry owner lookup only filters when origin is supplied: Current main's registry owner resolver accepts all plugin origins unless the caller supplies an origin, so passing origin: bundled intentionally excludes global/workspace/config plugin owners. (src/plugins/plugin-registry-contributions.ts:438, 2a7f9f354644)
  • PR active-snapshot override path filters to bundled owners: The PR's new active-runtime override matcher checks plugin-scoped webSearch/webFetch SecretRef paths with origin: bundled, which misses selected non-bundled web provider owners. (src/secrets/runtime-command-secrets.ts:122, 44fb025ade5d)
  • PR local fallback duplicates the bundled-only filter: The PR's gateway-unavailable local fallback override matcher also resolves webSearch/webFetch owners with origin: bundled, so selected external provider credentials can be classified inactive. (src/cli/command-secret-gateway.ts:193, 44fb025ade5d)
  • Prior review comments still match latest head: Existing review comments called out the same bundled-only provider owner filter in the active-snapshot and local-fallback override paths; the latest raw source still contains those checks at the cited lines. (44fb025ade5d)

Likely related people:

  • joshavant: Authored the current-main provider-backed command SecretRef fix that introduced the selected-provider target scoping this PR extends. (role: recent feature owner; confidence: high; commits: 2416de142194; files: src/cli/command-secret-targets.ts, src/cli/capability-cli.ts)
  • shakkernerd: Recent merged history scoped web provider ownership through the plugin index, which is the registry behavior the PR's override matching should preserve. (role: adjacent owner; confidence: medium; commits: 2e7635f4f97f; files: src/plugins/plugin-registry.ts, src/plugins/plugin-registry-contributions.ts, src/cli/command-secret-gateway.ts)
  • steipete: Recent merged history touches command-secret gateway surfaces, and the current PR branch changes the same CLI/gateway secret path. (role: recent area contributor; confidence: medium; commits: 900e21fb1ac6; files: src/cli/command-secret-gateway.ts)

Remaining risk / open question:

  • Focused tests and the live repro were not executed in this read-only pass; the repair should rerun the PR's focused validation after fixing the owner lookup.
  • The patch also changes the Gateway protocol model surface, so normal protocol/client compatibility checks should remain part of the PR gate.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 2a7f9f354644.

@steipete steipete force-pushed the fix/cli-web-search-secret-refs branch from f03421f to 8cbc656 Compare May 17, 2026 01:05

@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: f03421f1fb

ℹ️ 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/cli/capability-cli.ts Outdated
Comment on lines +1548 to +1552
targetIds: getCapabilityWebCommandSecretTargetIds(),
...(provider
? {
providerOverrides:
params.webKind === "search" ? { webSearch: provider } : { webFetch: provider },

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 Scope web secret targets to the active web command

resolveCapabilityCommandConfig always resolves the full getCapabilityWebCommandSecretTargetIds() set (search + fetch + plugin web refs), but only sends providerOverrides when --provider is explicitly passed. For default infer web search/infer web fetch runs, unrelated web surfaces remain in-scope, so an unresolved SecretRef on the other surface (for example, a broken tools.web.fetch... ref while running search) can still trigger enforced unresolved-secret failures and block the command even though that provider path is not used.

Useful? React with 👍 / 👎.

@steipete steipete force-pushed the fix/cli-web-search-secret-refs branch from 8cbc656 to d0af5da Compare May 17, 2026 01:09
@steipete steipete added the proof: override Maintainer override for the external PR real behavior proof gate. label May 17, 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: d0af5da09b

ℹ️ 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 on lines +122 to +126
resolveManifestContractOwnerPluginId({
contract: "webSearchProviders",
value: webSearch,
origin: "bundled",
config: params.config,

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 override owners across all plugin origins

The provider-override matching path is hard-coded to origin: "bundled", so infer web search/fetch --provider ... cannot activate SecretRefs for installed external providers even when getWeb*CommandSecretTargets selected those plugin paths. In that case isProviderOverridePath returns false for the selected plugin credential path, it gets treated as inactive, and command-secret resolution skips the credential for the provider the user explicitly chose. This is a regression introduced by the override flow and affects any non-bundled web provider with SecretRefs.

Useful? React with 👍 / 👎.

@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: e0343bb3e3

ℹ️ 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 on lines +193 to +197
commandSecretGatewayDeps.resolveManifestContractOwnerPluginId({
contract: "webSearchProviders",
value: webSearch,
origin: "bundled",
config: params.config,

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 override owners without bundled-only filtering

When resolveCommandSecretRefsViaGateway falls back to resolveCommandSecretRefsLocally (for example, gateway unavailable/unsupported), isProviderOverridePath resolves override owners with origin: "bundled", so external web providers selected via --provider are treated as inactive and their SecretRefs are skipped. This means local CLI runs can silently miss the selected provider credential (or degrade to unresolved behavior) even though allowedPaths selected that provider; the fresh evidence here is that this bundled-only filter is present in the new local-fallback override path, not just the server-side resolver already discussed.

Useful? React with 👍 / 👎.

@steipete steipete force-pushed the fix/cli-web-search-secret-refs branch from bd167de to 3fc6660 Compare May 17, 2026 01:46
@openclaw-barnacle openclaw-barnacle Bot added channel: whatsapp-web Channel integration: whatsapp-web extensions: memory-core Extension: memory-core labels May 17, 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: 44fb025ade

ℹ️ 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 on lines +115 to +117
const directProvider = searchProviderFromDirectWebPath(params.path);
if (directProvider) {
return directProvider === webSearch;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Canonicalize provider overrides before path matching

getWebSearchCommandSecretTargets/getWebFetchCommandSecretTargets normalize provider ids to lowercase, but isProviderOverridePath compares override values with normalizeOptionalString output, so mixed-case CLI input like --provider Gemini can select lowercase credential paths while this matcher treats them as non-selected and inactive. In that case the selected provider SecretRef can be reported unresolved (or skipped) even though the credential is configured, because direct-path checks and owner resolution run against the non-canonical override string.

Useful? React with 👍 / 👎.

@steipete

Copy link
Copy Markdown
Contributor Author

Verification for replacement fix for #82699 / #82621:

  • Codex review: /Users/steipete/Projects/agent-scripts/skills/codex-review/scripts/codex-review --mode branch clean after accepted findings fixed.
  • Focused tests after rebase: node scripts/run-vitest.mjs src/cli/command-secret-targets.test.ts src/commands/agent.runtime-config.test.ts src/secrets/runtime-command-secrets.test.ts src/cli/command-secret-gateway.test.ts src/gateway/server-methods/secrets.test.ts src/cli/capability-cli.test.ts src/cli/command-config-resolution.test.ts passed, 8 files / 141 tests.
  • Live repro: TAVILY_API_KEY=resolved-live-proof pnpm exec tsx scripts/repro/cli-web-search-secret-refs-live-proof.mjs passed. SecretRef stayed unresolved in raw config, command-time resolution produced a string, output stayed redacted, diagnostics count was 1.
  • CI-blocker boundary proof: OPENCLAW_ADDITIONAL_BOUNDARY_SHARD=4/4 OPENCLAW_ADDITIONAL_BOUNDARY_CONCURRENCY=4 node scripts/run-additional-boundary-checks.mjs passed, including lint:plugins:no-extension-test-core-imports.
  • Extension focused proof: node scripts/run-vitest.mjs extensions/memory-core/src/memory/qmd-manager.test.ts extensions/whatsapp/src/media.test.ts passed, 2 files / 128 tests.
  • Signal-account timeout follow-up: node scripts/run-vitest.mjs src/commands/channels.adds-non-default-telegram-account.test.ts passed, 1 file / 20 tests; failed CI shard was rerun and passed.
  • Crabbox live E2E: provider aws, lease cbx_aebcfe04e4bc (golden-hermit), run run_e442983bbd8d. Actions hydration 25977253055. Firecrawl plugin install/inspect succeeded. DuckDuckGo config and CLI override search both returned results. Live-key paths for Firecrawl/Gemini/xAI were exercised from allowlisted op export env, with expected provider-auth failures for expired/invalid keys and no secret values logged.
  • CI: latest SHA 44fb025ade5d9cae25ef385ecf263259772a2b7e; run 25978408516 green after rerunning the single timed-out shard.

Known gaps: live third-party provider calls proved SecretRef resolution and plugin install paths, but available Firecrawl/Gemini/xAI keys did not all authenticate successfully at the provider boundary. Raw AWS Crabbox image lacked Node, so E2E used Actions-hydrated Crabbox instead.

@steipete steipete merged commit 9e67f53 into main May 17, 2026
193 of 196 checks passed
@steipete steipete deleted the fix/cli-web-search-secret-refs branch May 17, 2026 02:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui channel: whatsapp-web Channel integration: whatsapp-web cli CLI command changes extensions: memory-core Extension: memory-core gateway Gateway runtime maintainer Maintainer-authored PR proof: override Maintainer override for the external PR real behavior proof gate. scripts Repository scripts size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: CLI web search does not resolve plugin-scoped webSearch SecretRefs

2 participants