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 <noreply@anthropic.com>
This commit is contained in:
7418andClaude Opus 4.6 committed 2026-02-13 16:01:22 +08:00
1 parent 916b8889b7
commit 83a0109af1
3 files changed
+26 -4

No files matched your search

+2 -2
View File
@@ -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",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "codepilot",
"version": "0.10.5",
"version": "0.10.6",
"private": true,
"author": {
"name": "op7418",
+23 -1
View File
@@ -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<string, string>): Record<string, string> {
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<strin
permissionMode: skipPermissions
? 'bypassPermissions'
: ((permissionMode as Options['permissionMode']) || 'acceptEdits'),
env: sdkEnv,
env: sanitizeEnv(sdkEnv),
};
if (skipPermissions) {