Skip to content

Fix infer SecretRef resolution for provider-backed commands#82798

Merged
joshavant merged 2 commits into
mainfrom
fix/infer-secretrefs-82621
May 17, 2026
Merged

Fix infer SecretRef resolution for provider-backed commands#82798
joshavant merged 2 commits into
mainfrom
fix/infer-secretrefs-82621

Conversation

@joshavant

Copy link
Copy Markdown
Contributor

Summary

  • Problem: local infer provider-backed commands could instantiate providers against raw config before command SecretRefs were resolved.
  • Why it matters: plugin-scoped web search/fetch credential refs could pass secrets audit but fail at runtime with unresolved SecretRef errors.
  • What changed: resolve command SecretRefs before local provider execution, scope web credential targets to the selected provider/fallback, and let web search use the explicitly resolved CLI config.
  • What did NOT change: no legacy config migration and no successful live Tavily query is claimed without a real key.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Real behavior proof

Behavior addressed: CLI web search resolves plugin-scoped webSearch.apiKey SecretRefs before invoking the local provider.

Real environment tested: AWS Crabbox Linux, provider aws, lease cbx_b66e354b1546, run run_71a9ceeecc03, isolated OpenClaw config and gateway.

Exact steps or command run after this patch: configured Tavily plugin plugins.entries.tavily.config.webSearch.apiKey as an env SecretRef, started a local gateway, then ran infer web search --provider tavily --query ping --limit 1 --json using a dummy TAVILY_API_KEY.

Evidence after fix: AWS proof output showed ASSERT_UNRESOLVED_SECRETREF=absent and GATEWAY_SECRETS_RESOLVE_SEEN=1; the command reached Tavily and returned 401 Unauthorized: missing or invalid API key, which is expected for the dummy key.

Observed result after fix: the command crossed the SecretRef resolution boundary and failed only at provider auth with the intentionally fake key.

What was not tested: a successful live Tavily result with a real Tavily API key.

Before evidence: current-main AWS repro on bea4f0d2f4b48ddd62db45970e513441e9af8f98 failed with unresolved SecretRef "env:default:TAVILY_API_KEY" while secrets audit reported unresolved=0.

Root Cause

  • Root cause: local provider-backed infer paths read raw getRuntimeConfig() and constructed providers directly, bypassing the command SecretRef resolver used by other command surfaces.
  • Missing detection / guardrail: command-secret resolution coverage did not include src/cli/capability-cli.ts, and web search runtime could prefer a stale runtime snapshot over the resolved CLI config.
  • Contributing context: web search/fetch need provider-specific credential target scoping so unrelated configured refs do not block a selected provider.

Regression Test Plan

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
  • Target test or file: src/cli/capability-cli.test.ts, src/cli/command-secret-targets.test.ts, src/web-search/runtime.test.ts, src/cli/command-secret-resolution.coverage.test.ts.
  • Scenario the test should lock in: local infer commands resolve command SecretRefs before provider construction and web search/fetch target only selected-provider credential paths.
  • Why this is the smallest reliable guardrail: it exercises the CLI boundary, command target selection, and web-search runtime snapshot behavior without requiring a live provider key.
  • Existing test that already covers this (if any): none covered this exact local infer SecretRef bypass.

User-visible / Behavior Changes

Local infer provider-backed commands can now use command SecretRefs before provider execution. Web search/fetch plugin-scoped credentials work through the selected provider path.

Diagram

Before:
infer web search -> raw config -> provider reads unresolved SecretRef -> failure

After:
infer web search -> command SecretRef resolver -> resolved config -> provider auth/network

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: command-scoped SecretRefs are resolved earlier for local provider execution using the existing command resolver and selected-provider allowedPaths, limiting resolution to the relevant credential paths.

Repro + Verification

Environment

  • OS: macOS local targeted tests; Linux AWS Crabbox and Blacksmith Testbox remote proof
  • Runtime/container: Node 22, pnpm 11.1.0
  • Model/provider: Tavily web search with dummy key for auth-boundary proof
  • Integration/channel (if any): Web search
  • Relevant config (redacted): Tavily plugin webSearch.apiKey as env SecretRef TAVILY_API_KEY

Steps

  1. Configure plugin-scoped Tavily webSearch.apiKey as an env SecretRef.
  2. Start the gateway from that config.
  3. Run infer web search --provider tavily --query ping --limit 1 --json.

Expected

  • No unresolved SecretRef error; with a dummy key, provider auth should fail after resolution.

Actual

  • AWS proof returned Tavily 401 for the dummy key, with unresolved SecretRef absent and secrets.resolve observed in gateway logs.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: focused local tests, Testbox pnpm check:changed, AWS E2E reproduction of the CLI/gateway/provider path.
  • Edge cases checked: selected provider credential scoping, Gemini model-provider fallback, Firecrawl webFetch/webSearch fallback, external provider owner mapping, stale web-search runtime snapshot handling.
  • What you did not verify: successful Tavily live search with a real key.

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
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: resolving too many unrelated credential refs for web commands could block selected-provider usage.
    • Mitigation: web search/fetch target selection now scopes allowedPaths to selected provider credentials and known same-provider fallbacks.

@openclaw-barnacle openclaw-barnacle Bot added cli CLI command changes size: L maintainer Maintainer-authored PR labels May 17, 2026
@clawsweeper

clawsweeper Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

Codex review: found issues before merge.

Summary
The branch resolves command SecretRefs before local infer provider execution, adds selected-provider web search/fetch secret target selection, updates web-search runtime config selection, tests, and a changelog entry.

Reproducibility: yes. The linked issue provides a concrete CLI repro, and current main's source shows local web search/fetch read raw runtime config before command SecretRef resolution.

Real behavior proof
Sufficient (live_output): The PR body includes AWS Crabbox live output showing the unresolved SecretRef is absent and the command reaches the expected Tavily 401 with a dummy key after resolution.

Next step before merge
This protected open PR needs the author or maintainer to revise the secrets-boundary behavior; it is not a separate ClawSweeper repair-lane candidate.

Security
Needs attention: The patch changes secrets handling and does not yet enforce selected-provider scoping before gateway secret resolution.

Review findings

  • [P2] Scope gateway resolution before applying web target secrets — src/cli/capability-cli.ts:1623-1624
Review details

Best possible solution:

Carry selected allowedPaths through the gateway secrets.resolve contract, or otherwise filter before gateway resolution and before applying assignments, then cover web search/fetch selected-provider and fallback cases against the gateway snapshot path.

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

Yes. The linked issue provides a concrete CLI repro, and current main's source shows local web search/fetch read raw runtime config before command SecretRef resolution.

Is this the best way to solve the issue?

No. Resolving SecretRefs before provider construction is the right direction, but this patch scopes paths only after the gateway has resolved and returned broad target assignments.

Full review comments:

  • [P2] Scope gateway resolution before applying web target secrets — src/cli/capability-cli.ts:1623-1624
    The new web command path passes selected-provider allowedPaths only into the local resolver call, but resolveCommandSecretRefsViaGateway still sends the gateway only broad targetIds and applies every returned assignment before the allowed-path analysis. With --provider tavily while the active snapshot selects another web provider, the gateway can resolve/apply the wrong provider secret and leave the selected SecretRef treated as inactive or unresolved. Carry the selected paths through the RPC, or filter before resolving and applying assignments.
    Confidence: 0.86

Overall correctness: patch is incorrect
Overall confidence: 0.86

Security concerns:

  • [medium] Gateway can over-resolve non-selected provider secrets — src/cli/capability-cli.ts:1623
    For provider-scoped web commands, allowedPaths is not sent to secrets.resolve; broad target IDs can cause the active gateway snapshot to return another provider's secret, which is then applied to the resolved config before scoped analysis. That weakens the intended selected-provider secret boundary.
    Confidence: 0.84

Acceptance criteria:

  • node scripts/run-vitest.mjs src/cli/command-secret-gateway.test.ts
  • node scripts/run-vitest.mjs src/cli/capability-cli.test.ts -t "web search"
  • node scripts/run-vitest.mjs src/cli/command-secret-targets.test.ts
  • Crabbox/Testbox proof for infer web search --provider tavily with a gateway runtime snapshot and a dummy Tavily key

What I checked:

  • Live PR state: The live PR API shows this PR is open at head 88560e0 with labels including maintainer, proof: sufficient, and P2. (88560e06bf64)
  • Related issue repro: The linked issue Bug: CLI web search does not resolve plugin-scoped webSearch SecretRefs #82621 reports openclaw infer web search --provider tavily failing on an unresolved plugin-scoped webSearch.apiKey SecretRef while secrets audit reports no unresolved refs.
  • Current-main raw config boundary: On current main, local infer web search reads getRuntimeConfig() and passes it directly into runWebSearch, matching the reported pre-fix boundary. (src/cli/capability-cli.ts:1529, d1280a3de939)
  • PR scoped local call: The PR head computes web search secret targets and passes secretTargets.allowedPaths into resolveLocalCapabilityRuntimeConfig before running the provider. (src/cli/capability-cli.ts:1621, 88560e06bf64)
  • Gateway request omits allowed paths: Current main's command-secret gateway still sends only commandName and targetIds in the secrets.resolve RPC params, so the selected path filter does not reach the gateway before resolution. (src/cli/command-secret-gateway.ts:690, d1280a3de939)
  • Assignments applied before scoped analysis: Current main applies every returned gateway assignment into resolvedConfig before analyzeCommandSecretAssignmentsFromSnapshot receives allowedPaths, so non-selected provider assignments can be materialized locally first. (src/cli/command-secret-gateway.ts:743, d1280a3de939)

Likely related people:

  • joshavant: Recent merged SecretRef lifecycle and scoped channel/account SecretRef commits changed the same command-secret and runtime resolution area, and the linked issue is assigned to this user. (role: recent adjacent SecretRef contributor; confidence: medium; commits: 1769fb2aa1d6, 731d4666d25f; files: src/cli/command-secret-gateway.ts, src/secrets/command-config.ts, src/secrets/runtime-command-secrets.ts)
  • Peter Steinberger: Local blame for the current central CLI and command-secret files in this checkout points to Peter Steinberger's current-main snapshot commit, making him a practical routing candidate for this area. (role: current-main carrier for affected files; confidence: medium; commits: fd8afc1dce46; files: src/cli/capability-cli.ts, src/cli/command-secret-targets.ts, src/cli/command-secret-gateway.ts)

Remaining risk / open question:

  • I did not run tests in this read-only review; the verdict is based on source inspection, PR body proof, and live GitHub metadata.

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

@joshavant joshavant force-pushed the fix/infer-secretrefs-82621 branch from c0804a3 to 71e9d05 Compare May 17, 2026 00:11
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. P2 Normal backlog priority with limited blast radius. labels May 17, 2026
@openclaw-barnacle openclaw-barnacle Bot added the gateway Gateway runtime label May 17, 2026
@joshavant joshavant force-pushed the fix/infer-secretrefs-82621 branch from 091061d to 88560e0 Compare May 17, 2026 00:27
@openclaw-barnacle openclaw-barnacle Bot removed the gateway Gateway runtime label May 17, 2026
@joshavant joshavant merged commit 2416de1 into main May 17, 2026
115 of 117 checks passed
@joshavant joshavant deleted the fix/infer-secretrefs-82621 branch May 17, 2026 00:55
galiniliev pushed a commit to galiniliev/openclaw that referenced this pull request May 20, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
galiniliev pushed a commit to galiniliev/openclaw that referenced this pull request May 25, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
SYU8384 pushed a commit to SYU8384/openclaw that referenced this pull request Jun 3, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
…#82798)

* fix infer secretref resolution

* chore changelog for infer secretrefs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli CLI command changes maintainer Maintainer-authored PR P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant