mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-03 04:17:54 +00:00
fix(delegation): strip claudecode in core delegation spawn paths
- add shared CLAUDECODE sanitizer for child env construction - apply sanitizer in execClaude and headless delegation execution - sanitize GLMT embedded Claude spawn environment Refs #588
This commit is contained in:
+3
-3
@@ -37,7 +37,7 @@ import { handleShellCompletionCommand } from './commands/shell-completion-comman
|
|||||||
import { handleUpdateCommand } from './commands/update-command';
|
import { handleUpdateCommand } from './commands/update-command';
|
||||||
|
|
||||||
// Import extracted utility functions
|
// Import extracted utility functions
|
||||||
import { execClaude, escapeShellArg } from './utils/shell-executor';
|
import { execClaude, escapeShellArg, stripClaudeCodeEnv } from './utils/shell-executor';
|
||||||
import { wireChildProcessSignals } from './utils/signal-forwarder';
|
import { wireChildProcessSignals } from './utils/signal-forwarder';
|
||||||
|
|
||||||
// Import target adapter system
|
// Import target adapter system
|
||||||
@@ -197,13 +197,13 @@ async function execClaudeWithProxy(
|
|||||||
const needsShell = isWindows && /\.(cmd|bat)$/i.test(claudeCli);
|
const needsShell = isWindows && /\.(cmd|bat)$/i.test(claudeCli);
|
||||||
const webSearchEnv = getWebSearchHookEnv();
|
const webSearchEnv = getWebSearchHookEnv();
|
||||||
const imageAnalysisEnv = getImageAnalysisHookEnv(profileName);
|
const imageAnalysisEnv = getImageAnalysisHookEnv(profileName);
|
||||||
const env = {
|
const env = stripClaudeCodeEnv({
|
||||||
...process.env,
|
...process.env,
|
||||||
...envVars,
|
...envVars,
|
||||||
...webSearchEnv,
|
...webSearchEnv,
|
||||||
...imageAnalysisEnv,
|
...imageAnalysisEnv,
|
||||||
CCS_PROFILE_TYPE: 'settings', // Signal to WebSearch hook this is a third-party provider
|
CCS_PROFILE_TYPE: 'settings', // Signal to WebSearch hook this is a third-party provider
|
||||||
};
|
});
|
||||||
|
|
||||||
let claude: ChildProcess;
|
let claude: ChildProcess;
|
||||||
if (isPowerShellScript) {
|
if (isPowerShellScript) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { StreamBuffer, formatToolVerbose } from './executor/stream-parser';
|
|||||||
import { buildExecutionResult } from './executor/result-aggregator';
|
import { buildExecutionResult } from './executor/result-aggregator';
|
||||||
import { getCcsDir, getModelDisplayName } from '../utils/config-manager';
|
import { getCcsDir, getModelDisplayName } from '../utils/config-manager';
|
||||||
import { getProfileLookupCandidates } from '../utils/profile-compat';
|
import { getProfileLookupCandidates } from '../utils/profile-compat';
|
||||||
|
import { stripClaudeCodeEnv } from '../utils/shell-executor';
|
||||||
|
|
||||||
// Re-export types for consumers
|
// Re-export types for consumers
|
||||||
export type { ExecutionOptions, ExecutionResult, StreamMessage } from './executor/types';
|
export type { ExecutionOptions, ExecutionResult, StreamMessage } from './executor/types';
|
||||||
@@ -209,7 +210,7 @@ export class HeadlessExecutor {
|
|||||||
|
|
||||||
// Strip Claude Code nested session guard env var to allow CCS delegation
|
// Strip Claude Code nested session guard env var to allow CCS delegation
|
||||||
// (Claude Code v2.1.39+ sets CLAUDECODE to detect nested sessions)
|
// (Claude Code v2.1.39+ sets CLAUDECODE to detect nested sessions)
|
||||||
const { CLAUDECODE: _nested, ...cleanEnv } = process.env;
|
const cleanEnv = stripClaudeCodeEnv(process.env);
|
||||||
|
|
||||||
const proc = spawn(claudeCli, args, {
|
const proc = spawn(claudeCli, args, {
|
||||||
cwd,
|
cwd,
|
||||||
|
|||||||
@@ -24,6 +24,22 @@ export function stripAnthropicEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strip Claude Code nested-session guard env var from a process environment.
|
||||||
|
*
|
||||||
|
* Note: Windows env keys are case-insensitive, so remove case-insensitively
|
||||||
|
* to avoid missing variants like `claudecode`.
|
||||||
|
*/
|
||||||
|
export function stripClaudeCodeEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
||||||
|
const result: NodeJS.ProcessEnv = {};
|
||||||
|
for (const key of Object.keys(env)) {
|
||||||
|
if (key.toUpperCase() !== 'CLAUDECODE') {
|
||||||
|
result[key] = env[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escape arguments for shell execution (cross-platform)
|
* Escape arguments for shell execution (cross-platform)
|
||||||
*
|
*
|
||||||
@@ -80,13 +96,13 @@ export function execClaude(
|
|||||||
: process.env;
|
: process.env;
|
||||||
|
|
||||||
// Prepare environment (merge with base env if envVars provided)
|
// Prepare environment (merge with base env if envVars provided)
|
||||||
const env = envVars
|
const mergedEnv = envVars
|
||||||
? { ...baseEnv, ...envVars, ...webSearchEnv }
|
? { ...baseEnv, ...envVars, ...webSearchEnv }
|
||||||
: { ...baseEnv, ...webSearchEnv };
|
: { ...baseEnv, ...webSearchEnv };
|
||||||
|
|
||||||
// Strip Claude Code nested session guard env var to allow CCS delegation
|
// Strip Claude Code nested session guard env var to allow CCS delegation
|
||||||
// (Claude Code v2.1.39+ sets CLAUDECODE to detect nested sessions)
|
// (Claude Code v2.1.39+ sets CLAUDECODE to detect nested sessions)
|
||||||
delete env.CLAUDECODE;
|
const env = stripClaudeCodeEnv(mergedEnv);
|
||||||
|
|
||||||
// propagate key env vars to tmux session so agent team teammates
|
// propagate key env vars to tmux session so agent team teammates
|
||||||
// (spawned via tmux split-window) inherit the correct config dir
|
// (spawned via tmux split-window) inherit the correct config dir
|
||||||
|
|||||||
Reference in New Issue
Block a user