From 83a0109af1eb05410c1b8ef945bd55db367e60d7 Mon Sep 17 00:00:00 2001 From: 7418 <7418@openclaw.ai> Date: Fri, 13 Feb 2026 16:01:22 +0800 Subject: [PATCH] fix: sanitize env variables to prevent spawn EINVAL with third-party API providers Strip null bytes and control characters from environment variable values before passing them to child_process.spawn via the SDK. Third-party Anthropic API providers could introduce invalid characters through api_key, base_url, or extra_env, causing spawn EINVAL errors. Bump version to 0.10.6. Co-Authored-By: Claude Opus 4.6 --- package-lock.json | 4 ++-- package.json | 2 +- src/lib/claude-client.ts | 24 +++++++++++++++++++++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index b544fc5..53b95d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codepilot", - "version": "0.10.5", + "version": "0.10.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codepilot", - "version": "0.10.5", + "version": "0.10.6", "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.33", "@hugeicons/core-free-icons": "^3.1.1", diff --git a/package.json b/package.json index f433d9f..90b4341 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codepilot", - "version": "0.10.5", + "version": "0.10.6", "private": true, "author": { "name": "op7418", diff --git a/src/lib/claude-client.ts b/src/lib/claude-client.ts index deae504..05a6a5b 100644 --- a/src/lib/claude-client.ts +++ b/src/lib/claude-client.ts @@ -24,6 +24,28 @@ import os from 'os'; import fs from 'fs'; import path from 'path'; +/** + * Sanitize a string for use as an environment variable value. + * Removes null bytes and control characters that cause spawn EINVAL. + */ +function sanitizeEnvValue(value: string): string { + // eslint-disable-next-line no-control-regex + return value.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, ''); +} + +/** + * Sanitize all values in an env record so child_process.spawn won't + * throw EINVAL due to invalid characters (null bytes, control chars). + */ +function sanitizeEnv(env: Record): Record { + for (const [key, value] of Object.entries(env)) { + if (typeof value === 'string') { + env[key] = sanitizeEnvValue(value); + } + } + return env; +} + let cachedClaudePath: string | null | undefined; function findClaudePath(): string | undefined { @@ -262,7 +284,7 @@ export function streamClaude(options: ClaudeStreamOptions): ReadableStream