Skip to content

fix(acp): strip provider auth env for child ACP processes#42250

Merged
Takhoffman merged 7 commits intoopenclaw:mainfrom
rodrigouroz:codex/acp-provider-auth-env-minimal
Mar 10, 2026
Merged

fix(acp): strip provider auth env for child ACP processes#42250
Takhoffman merged 7 commits intoopenclaw:mainfrom
rodrigouroz:codex/acp-provider-auth-env-minimal

Conversation

@rodrigouroz
Copy link
Copy Markdown
Contributor

@rodrigouroz rodrigouroz commented Mar 10, 2026

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: provider auth env vars such as OPENAI_API_KEY, GITHUB_TOKEN, and HF_TOKEN can leak into ACP child processes.
  • Why it matters: downstream ACP agents can detect inherited provider creds and switch auth modes or overwrite their own auth state.
  • What changed: the default OpenClaw ACP bridge path and bundled acpx spawn path now strip a shared list of provider auth env vars before spawning child ACP processes.
  • What did NOT change (scope boundary): explicit custom ACP servers and explicit custom acpx commands still inherit their env-based auth contract.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • 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

User-visible / Behavior Changes

  • Default openclaw acp child processes no longer inherit provider auth env vars from the parent OpenClaw process.
  • Bundled acpx child processes no longer inherit provider auth env vars from the parent OpenClaw process.
  • Explicit custom ACP servers and custom acpx commands continue to inherit provider auth env vars.
  • secrets audit and secrets apply now treat additional provider auth env vars such as GITHUB_TOKEN, GH_TOKEN, COPILOT_GITHUB_TOKEN, and ANTHROPIC_OAUTH_TOKEN as secrets, so plaintext .env entries for those keys are now flagged and scrubbed too.

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) Yes
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:
    Provider auth env vars are now scrubbed before spawning default ACP child processes. This reduces unintended credential propagation. The main compatibility risk is breaking custom servers that rely on inherited creds, so the strip only applies to the default OpenClaw bridge path and bundled acpx path, not explicit custom commands. As part of unifying the secret list, secrets audit and secrets apply now also treat additional provider tokens like GITHUB_TOKEN and GH_TOKEN as secrets.

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: Node 22 / pnpm
  • Model/provider: N/A
  • Integration/channel (if any): ACP / ACPX
  • Relevant config (redacted): default ACP bridge path, bundled acpx, explicit custom ACP server command, explicit custom acpx command

Steps

  1. Export provider auth env vars like OPENAI_API_KEY, GITHUB_TOKEN, and HF_TOKEN in the parent shell.
  2. Start ACP through the default OpenClaw bridge path or bundled acpx path.
  3. Inspect the spawned child env and then repeat with an explicit custom ACP server or explicit custom acpx command.

Expected

  • Default OpenClaw ACP child processes do not receive provider auth env vars.
  • OPENCLAW_API_KEY remains available.
  • Explicit custom ACP servers and explicit custom acpx commands still receive inherited provider auth env vars.

Actual

  • Verified locally: behavior matches the expected cases above.

Evidence

Attach at least one:

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

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: default ACP bridge strips provider auth vars; bundled acpx strips provider auth vars; explicit custom ACP servers preserve provider auth vars; explicit custom acpx commands preserve provider auth vars.
  • Edge cases checked: OPENCLAW_API_KEY is preserved; non-_API_KEY auth vars like GITHUB_TOKEN and HF_TOKEN are stripped where intended; src/plugin-sdk/subpaths.test.ts still passes on the clean branch.
  • What you did not verify: full GitHub Actions run on the new PR branch; behavior on Windows beyond existing spawn-path unit coverage.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert this PR or temporarily run ACP through an explicit custom server/custom acpx command path.
  • Files/config to restore: src/acp/client.ts, extensions/acpx/src/runtime-internals/process.ts, extensions/acpx/src/runtime.ts, src/secrets/provider-env-vars.ts
  • Known bad symptoms reviewers should watch for: default ACP bridge or bundled acpx unexpectedly losing access to required provider creds; explicit custom commands unexpectedly losing inherited creds.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: the shared provider-auth env var list misses a provider-specific token name and leaves an unintended credential in child env.
    • Mitigation: centralize the list in src/secrets/provider-env-vars.ts and cover non-_API_KEY examples in tests.
  • Risk: stripping env vars too broadly breaks custom user-managed ACP server setups.
    • Mitigation: only strip on the default OpenClaw bridge path and bundled acpx path; explicit custom commands preserve inherited env vars.

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: a9bcf2c8b5

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

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 10, 2026

Greptile Summary

This PR adds a security hardening layer to prevent provider authentication environment variables (such as OPENAI_API_KEY, GITHUB_TOKEN, and HF_TOKEN) from leaking into child ACP and ACPX processes. The fix is well-scoped: stripping is only applied on the default OpenClaw bridge path and the bundled acpx binary, while explicit custom server commands preserve their inherited environment. The three previously-flagged concerns (redundant OPENCLAW_API_KEY guard, allowPluginLocalInstall security coupling, and quoteCommandPart escaping) have all been addressed in earlier commits on this branch.

Key changes:

  • src/secrets/provider-env-vars.ts — new EXTRA_PROVIDER_AUTH_ENV_VARS list, listKnownProviderAuthEnvVarNames(), and omitEnvKeysCaseInsensitive() centralise the strip logic with case-insensitive matching.
  • extensions/acpx/src/config.ts — explicit stripProviderAuthEnvVars field added to ResolvedAcpxPluginConfig, derived cleanly from command === ACPX_BUNDLED_BIN.
  • extensions/acpx/src/runtime.tsstripProviderAuthEnvVars threaded through all four spawn call sites.
  • src/acp/client.tsshouldStripProviderAuthEnvVarsForAcpServer correctly compares the full (command, args) tuple so an explicit custom command that happens to use the same executable but different args is not stripped.
  • One undocumented side effect worth noting: listKnownSecretEnvVarNames now delegates to listKnownProviderAuthEnvVarNames, expanding the set of tokens recognised by secrets audit and secrets apply (see inline comment on provider-env-vars.ts).

Confidence Score: 4/5

  • Safe to merge with one minor undocumented behavioral change to note for operators
  • The core env-stripping logic is correct, case-insensitive, and well-tested at all four ACPX spawn sites and the ACP client path. The explicit stripProviderAuthEnvVars config field properly decouples the security decision from allowPluginLocalInstall. The shouldStripProviderAuthEnvVarsForAcpServer comparison is reliable for both the entryPath and non-entryPath cases. Score is 4 rather than 5 because listKnownSecretEnvVarNames silently expanding its returned set has an unannounced behavioral effect on secrets audit and secrets apply for tokens like GITHUB_TOKEN and COPILOT_GITHUB_TOKEN — not a correctness bug but potentially surprising for existing users of those features.
  • src/secrets/provider-env-vars.ts — the expansion of listKnownSecretEnvVarNames affects secrets audit/apply outside the stated ACP scope and should be explicitly documented for operators.

Last reviewed commit: 9c7ed9c

@rodrigouroz
Copy link
Copy Markdown
Contributor Author

Follow-up in 44e2192.

Addressed the review points in the minimal patch:

  • ACP client stripping now keys off the resolved default-bridge command, so an explicit --server openclaw still strips provider auth env vars.
  • Secret handling uses one shared provider-auth env list now, so audit/apply pick up extra tokens like GITHUB_TOKEN, GH_TOKEN, and ANTHROPIC_OAUTH_TOKEN too.
  • Env stripping is now case-insensitive in both the ACP client path and the ACPX child-spawn path, which closes the Windows mixed-case bypass.
  • ACPX child stripping is now opt-in at the runtime callsites instead of default-on, so hidden/custom callers do not silently lose inherited provider creds.

Verification:

  • pnpm exec oxfmt --check src/secrets/provider-env-vars.ts src/secrets/provider-env-vars.test.ts src/plugin-sdk/acpx.ts src/plugin-sdk/subpaths.test.ts src/acp/client.ts src/acp/client.test.ts extensions/acpx/src/runtime-internals/process.ts extensions/acpx/src/runtime-internals/process.test.ts extensions/acpx/src/runtime.ts
  • pnpm test -- src/secrets/provider-env-vars.test.ts src/acp/client.test.ts extensions/acpx/src/runtime-internals/process.test.ts extensions/acpx/src/runtime.test.ts

Local note: src/plugin-sdk/subpaths.test.ts still fails in this checkout on the unrelated stale bluebubbles.parseFiniteNumber export mismatch; the ACPX helper assertion itself is not the failing line.

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: 44e219238c

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

@rodrigouroz
Copy link
Copy Markdown
Contributor Author

@greptileai review now

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: 77ec72ec6b

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

@rodrigouroz
Copy link
Copy Markdown
Contributor Author

@greptileai review now

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: 2e89443791

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

@rodrigouroz
Copy link
Copy Markdown
Contributor Author

Follow-up in 9c7ed9c.

Greptile was right about the unrelated Windows quoting regression in extensions/acpx/src/runtime-internals/mcp-agent-command.ts: the replacement string had been over-escaped (\\$& instead of \$&), which would corrupt quoted proxy paths.

Fixed:

  • restored the original escaping in quoteCommandPart()
  • added a focused regression test in extensions/acpx/src/runtime-internals/mcp-agent-command.test.ts

Verification:

  • pnpm exec oxfmt --check extensions/acpx/src/runtime-internals/mcp-agent-command.ts extensions/acpx/src/runtime-internals/mcp-agent-command.test.ts
  • pnpm test -- extensions/acpx/src/runtime-internals/mcp-agent-command.test.ts

@rodrigouroz
Copy link
Copy Markdown
Contributor Author

@greptileai review now

@Takhoffman Takhoffman self-assigned this Mar 10, 2026
@Takhoffman Takhoffman force-pushed the codex/acp-provider-auth-env-minimal branch from 9c7ed9c to 0f67c17 Compare March 10, 2026 21:41
@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot bot commented Mar 10, 2026

🔒 Aisle Security Analysis

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

# Severity Title
1 🟡 Medium Brittle command string equality can disable provider auth env var stripping for the bundled acpx binary

1. 🟡 Brittle command string equality can disable provider auth env var stripping for the bundled acpx binary

Property Value
Severity Medium
CWE CWE-200
Location extensions/acpx/src/config.ts:331-337

Description

stripProviderAuthEnvVars is derived solely from a string equality check against ACPX_BUNDLED_BIN:

  • resolveConfiguredCommand() can resolve rawConfig.command to many semantically equivalent paths (different casing on case-insensitive filesystems, symlinks, alternate absolute paths) that still execute the same bundled binary.
  • If command !== ACPX_BUNDLED_BIN (string compare), stripProviderAuthEnvVars becomes false.
  • When stripProviderAuthEnvVars is false, spawned acpx / npm child processes inherit provider authentication environment variables (API keys/tokens) because spawnWithResolvedCommand() only strips when this flag is set.

This makes the stripping policy easy to accidentally (or intentionally) bypass while still running the bundled binary, resulting in unexpected exposure of provider credentials to child processes.

Vulnerable code:

const command = resolveConfiguredCommand({ configured: normalized.command, workspaceDir: params.workspaceDir });
const stripProviderAuthEnvVars = command === ACPX_BUNDLED_BIN;

Recommendation

Make the decision based on the canonical resolved executable rather than raw string equality, and/or allow an explicit config override with a secure default.

Option A (canonicalize paths):

import fs from "node:fs";

function sameExecutable(a: string, b: string): boolean {
  try {
    return fs.realpathSync(a) === fs.realpathSync(b);
  } catch {
    return false;
  }
}

const isBundled = sameExecutable(command, ACPX_BUNDLED_BIN);
const stripProviderAuthEnvVars = isBundled;

Option B (explicit config): add stripProviderAuthEnvVars?: boolean to the config schema, default it to true (or at minimum true for bundled), and document the security implications of disabling it.

Also consider normalizing case on Windows/macOS case-insensitive filesystems if relying on string comparison anywhere else.


Analyzed PR: #42250 at commit 0f67c17

Last updated on: 2026-03-10T21:59:29Z

@Takhoffman Takhoffman merged commit ff2e7a2 into openclaw:main Mar 10, 2026
28 checks passed
mrosmarin added a commit to mrosmarin/openclaw that referenced this pull request Mar 10, 2026
* main: (42 commits)
  test: share runtime group policy fallback cases
  refactor: share windows command shim resolution
  refactor: share approval gateway client setup
  refactor: share telegram payload send flow
  refactor: share passive account lifecycle helpers
  refactor: share channel config schema fragments
  refactor: share channel config security scaffolding
  refactor: share onboarding secret prompt flows
  refactor: share scoped account config patching
  feat(discord): add autoArchiveDuration config option (openclaw#35065)
  fix(gateway): harden token fallback/reconnect behavior and docs (openclaw#42507)
  fix(acp): strip provider auth env for child ACP processes (openclaw#42250)
  fix(browser): surface 429 rate limit errors with actionable hints (openclaw#40491)
  fix(acp): scope cancellation and event routing by runId (openclaw#41331)
  docs: require codex review in contributing guide (openclaw#42503)
  Fix stale runtime model reuse on session reset (openclaw#41173)
  docs: document r: spam auto-close label
  fix(ci): auto-close and lock r: spam items
  fix(acp): implicit streamToParent for mode=run without thread (openclaw#42404)
  test: extract sendpayload outbound contract suite
  ...
gumadeiras pushed a commit to BillChirico/openclaw that referenced this pull request Mar 11, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
frankekn pushed a commit to MoerAI/openclaw that referenced this pull request Mar 11, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
frankekn pushed a commit to Effet/openclaw that referenced this pull request Mar 11, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
frankekn pushed a commit to ImLukeF/openclaw that referenced this pull request Mar 11, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
Treedy2020 pushed a commit to Treedy2020/openclaw that referenced this pull request Mar 11, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
dhoman pushed a commit to dhoman/chrono-claw that referenced this pull request Mar 11, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
ahelpercn pushed a commit to ahelpercn/openclaw that referenced this pull request Mar 12, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
Ruijie-Ysp pushed a commit to Ruijie-Ysp/clawdbot that referenced this pull request Mar 12, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
leozhengliu-pixel pushed a commit to leozhengliu-pixel/openclaw that referenced this pull request Mar 13, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
Interstellar-code pushed a commit to Interstellar-code/operator1 that referenced this pull request Mar 16, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
(cherry picked from commit ff2e7a2)
senw-developers pushed a commit to senw-developers/va-openclaw that referenced this pull request Mar 17, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 23, 2026
…2250)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
(cherry picked from commit ff2e7a2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants