mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-10 07:52:44 +00:00
* fix: strip skill-injected env vars from ACP harness spawn env Skill apiKey entries (e.g., openai-image-gen with primaryEnv=OPENAI_API_KEY) are set on process.env during agent runs and only reverted after the run completes. ACP harnesses like Codex CLI inherit these vars, causing them to silently use API billing instead of their own auth (e.g., OAuth). The fix tracks which env vars are actively injected by skill overrides in a module-level Set (activeSkillEnvKeys) and strips them in resolveAcpClientSpawnEnv() before spawning ACP child processes. Fixes #36280 * ACP: type spawn env for stripped keys * Skills: cover active env key lifecycle * Changelog: note ACP skill env isolation * ACP: preserve shell marker after env stripping --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
buildWorkspaceSkillSnapshot,
|
||||
loadWorkspaceSkillEntries,
|
||||
} from "./skills.js";
|
||||
import { getActiveSkillEnvKeys } from "./skills/env-overrides.js";
|
||||
|
||||
const fixtureSuite = createFixtureSuite("openclaw-skills-suite-");
|
||||
let tempHome: TempHomeEnv | null = null;
|
||||
@@ -256,9 +257,11 @@ describe("applySkillEnvOverrides", () => {
|
||||
|
||||
try {
|
||||
expect(process.env.ENV_KEY).toBe("injected");
|
||||
expect(getActiveSkillEnvKeys().has("ENV_KEY")).toBe(true);
|
||||
} finally {
|
||||
restore();
|
||||
expect(process.env.ENV_KEY).toBeUndefined();
|
||||
expect(getActiveSkillEnvKeys().has("ENV_KEY")).toBe(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
1
src/agents/skills/env-overrides.runtime.ts
Normal file
1
src/agents/skills/env-overrides.runtime.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { getActiveSkillEnvKeys } from "./env-overrides.js";
|
||||
@@ -12,6 +12,19 @@ const log = createSubsystemLogger("env-overrides");
|
||||
type EnvUpdate = { key: string; prev: string | undefined };
|
||||
type SkillConfig = NonNullable<ReturnType<typeof resolveSkillConfig>>;
|
||||
|
||||
/**
|
||||
* Tracks env var keys that are currently injected by skill overrides.
|
||||
* Used by ACP harness spawn to strip skill-injected keys so they don't
|
||||
* leak to child processes (e.g., OPENAI_API_KEY leaking to Codex CLI).
|
||||
* @see https://github.com/openclaw/openclaw/issues/36280
|
||||
*/
|
||||
const activeSkillEnvKeys = new Set<string>();
|
||||
|
||||
/** Returns a snapshot of env var keys currently injected by skill overrides. */
|
||||
export function getActiveSkillEnvKeys(): ReadonlySet<string> {
|
||||
return activeSkillEnvKeys;
|
||||
}
|
||||
|
||||
type SanitizedSkillEnvOverrides = {
|
||||
allowed: Record<string, string>;
|
||||
blocked: string[];
|
||||
@@ -135,12 +148,14 @@ function applySkillConfigEnvOverrides(params: {
|
||||
}
|
||||
updates.push({ key: envKey, prev: process.env[envKey] });
|
||||
process.env[envKey] = envValue;
|
||||
activeSkillEnvKeys.add(envKey);
|
||||
}
|
||||
}
|
||||
|
||||
function createEnvReverter(updates: EnvUpdate[]) {
|
||||
return () => {
|
||||
for (const update of updates) {
|
||||
activeSkillEnvKeys.delete(update.key);
|
||||
if (update.prev === undefined) {
|
||||
delete process.env[update.key];
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user