CherryHQ/cherry-studio · error · Error
Invalid MCP package env: environment variable "${key}" is no
Error message
Invalid MCP package env: environment variable "${key}" is not allowed What it means
Thrown by buildResolvedEnv when an environment variable key matches the process-affecting denylist. The denylist is NODE_OPTIONS, LD_PRELOAD, LD_LIBRARY_PATH (case-insensitive, compared via canonicalKey.toUpperCase()) plus any key starting with DYLD_. These variables can change code loading in the spawned MCP server (preload a shared library, inject Node flags), so a manifest setting them could run arbitrary code despite command/arg validation.
Source
Thrown at src/main/ai/mcp/McpPackageService.ts:263
*
* @throws Error if a key/value contains a null byte or a key is denylisted
*/
export function buildResolvedEnv(
env: Record<string, string>,
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 {View on GitHub (pinned to 726446b54c)
Solutions
- Remove the denylisted key from the manifest's env (and platform_overrides.env) and find an alternative that does not alter process code-loading (e.g. set memory limits via a wrapper script rather than NODE_OPTIONS).
- If the variable is required for the server to run, bundle the prerequisite into the package itself (the .so / .node file inside the extract dir) and reference it via a relative path the command resolves, not via LD_PRELOAD.
- Repackage and re-upload.
Example fix
// manifest.json - before
"env": { "NODE_OPTIONS": "--max-old-space-size=4096" }
// after
"env": {},
"args": ["--max-old-space-size=4096"] // pass to the runtime via args instead Defensive patterns
Strategy: validation
Validate before calling
const DXT_ENV_DENYLIST = ['NODE_OPTIONS', 'LD_PRELOAD', 'LD_LIBRARY_PATH']
function isAllowedEnvKey(key: string): boolean {
const canonical = key.toUpperCase()
return !DXT_ENV_DENYLIST.includes(canonical) && !canonical.startsWith('DYLD_')
}
function allEnvKeysAllowed(env: Record<string, string>): boolean {
return Object.keys(env).every(isAllowedEnvKey)
} Type guard
function isNonDeniedEnvKey(key: string): boolean {
const canonical = key.toUpperCase()
return !['NODE_OPTIONS', 'LD_PRELOAD', 'LD_LIBRARY_PATH'].includes(canonical)
&& !canonical.startsWith('DYLD_')
} Prevention
- Document the denylist in your package-author guide so authors do not attempt to set NODE_OPTIONS or LD_PRELOAD.
- Run a manifest linter in CI that flags denylisted env keys before publishing a package.
- If a runtime genuinely needs an env var to tune behavior, pass it via args instead.
When it happens
Trigger: A manifest env map contains {"NODE_OPTIONS": "--require /tmp/evil.js"}, {"LD_PRELOAD": "/x.so"}, {"DYLD_INSERT_LIBRARIES": "..."}, or any casing variant like "node_options". Platform overrides that merge an env map with one of these keys also trigger it.
Common situations: A package author legitimately wanted to tune Node memory flags via NODE_OPTIONS; a package copied a shell environment that included LD_LIBRARY_PATH; a macOS-targeted override set a DYLD_ variable for code signing reasons.
Related errors
- Invalid MCP package env: null byte detected in environment v
- Invalid MCP package env: null byte detected in value of envi
- Invalid args: path traversal detected in argument at index $
- Invalid command: command must be a non-empty string
- Invalid command: command cannot be empty
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/2183af56e31e5dbb.
Report an issue: GitHub.