CherryHQ/cherry-studio · error · Error
Invalid MCP package env: null byte detected in value of envi
Error message
Invalid MCP package env: null byte detected in value of environment variable "${key}" What it means
Thrown by buildResolvedEnv after variable substitution: an env value, once ${__dirname}, ${HOME}, ${user_config.*} etc. are expanded, contained a NUL byte. The check runs on the substituted value (performVariableSubstitution output), so the null can come from the manifest literally or be introduced by a user_config value injected via the ${user_config.KEY} template.
Source
Thrown at src/main/ai/mcp/McpPackageService.ts:268
extractDir: string,
userConfig?: Record<string, any>
): Record<string, string> {
const resolvedEnv: Record<string, string> = {}
for (const [key, value] of Object.entries(env)) {
if (key.includes('\0')) {
throw new Error('Invalid MCP package env: null byte detected in environment variable name')
}
// Denylist process-affecting variables (DYLD_* on macOS, plus exact matches above).
const canonicalKey = key.toUpperCase()
if (DXT_ENV_DENYLIST.includes(canonicalKey) || canonicalKey.startsWith('DYLD_')) {
throw new Error(`Invalid MCP package env: environment variable "${key}" is not allowed`)
}
const substituted = performVariableSubstitution(value, extractDir, userConfig)
if (substituted.includes('\0')) {
throw new Error(`Invalid MCP package env: null byte detected in value of environment variable "${key}"`)
}
resolvedEnv[key] = substituted
}
return resolvedEnv
}
export function validatePackageUploadPayload(
fileBuffer: ArrayBuffer | NodeJS.ArrayBufferView,
fileName: string,
packageFormat: McpPackageFormat
): Buffer {
if (typeof fileName !== 'string') {
throw new Error('Invalid MCP package upload: file name must be a string')
}
const trimmedFileName = fileName.trim()View on GitHub (pinned to 726446b54c)
Solutions
- Identify whether the null originated in the manifest value or in a ${user_config.*} substitution. Inspect the manifest's env values first.
- If it came from user_config, sanitize the user-supplied value in the package config form before it reaches the substitution (strip \0 and other control characters).
- Repackage the manifest with a clean value or re-enter the user config and retry.
Defensive patterns
Strategy: validation
Validate before calling
function hasNoNullByte(value: unknown): boolean {
return typeof value === 'string' && !value.includes('\0')
}
function cleanEnvValues(env: Record<string, string>, userConfig?: Record<string, any>): boolean {
// Mirror performVariableSubstitution only for user_config; __dirname/HOME do not inject nulls.
return Object.entries(env).every(([, v]) => {
if (!v.includes('\0')) return true
if (!userConfig) return false
const substituted = v.replace(/\$\{user_config\.([^}]+)\}/g, (_m, k) => userConfig[k] ?? _m)
return !substituted.includes('\0')
})
} Type guard
function isNullByteFree(value: unknown): value is string {
return typeof value === 'string' && !value.includes('\0')
} Prevention
- Strip control characters (including \0) from user_config form fields on the renderer before submission.
- In a manifest linter, flag env values that contain control characters or ${user_config.*} placeholders whose schema accepts free text.
- When authoring manifests, avoid embedding raw bytes; use base64 if binary data must be conveyed and decode in the server.
When it happens
Trigger: Manifest env value contains a literal \0; or a ${user_config.field} placeholder is filled by a user-supplied value that contains \0 and the substitution replaces the placeholder with it.
Common situations: A user-config text field accepted a pasted binary blob; a manifest author copied a value from a terminal that included a control character; a malicious package tried to smuggle a null past key-level validation by putting it in the value.
Related errors
- Invalid MCP package env: null byte detected in environment v
- Invalid MCP package env: environment variable "${key}" is no
- Invalid command: null byte detected
- Invalid args: null byte detected in argument at index ${inde
- Invalid args: path traversal detected in argument at index $
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/3778115d87188979.
Report an issue: GitHub.