bytedance/deer-flow · error · HTTPException
MCP server '{name}' sets environment variable '{env_name}',
Error message
MCP server '{name}' sets environment variable '{env_name}', which would run arbitrary code at process startup. What it means
400 raised when a stdio MCP server definition sets an environment variable whose name (case-insensitive) is in _CODE_INJECTING_ENV_VARS — variables like PYTHONSTARTUP, NODE_OPTIONS, LD_PRELOAD, PERL5OPT that cause code to run at process startup. This closes the gap where an allowlisted binary is hijacked via its runtime's startup hooks.
Source
Thrown at backend/app/gateway/routers/mcp.py:622
command_name = _stdio_command_name(server.command, server_name=name)
if command_name not in allowed_commands:
allowed = ", ".join(sorted(allowed_commands)) or "<none>"
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=(f"MCP server '{name}' uses disallowed stdio command '{command_name}'. Allowed commands: {allowed}. Configure {_MCP_STDIO_COMMAND_ALLOWLIST_ENV} to extend this list."),
)
exec_flag = _arbitrary_exec_arg(server.args, command=command_name)
if exec_flag is not None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=(f"MCP server '{name}' passes '{exec_flag}' to '{command_name}', which would run arbitrary code. Point the server at a package or module instead."),
)
for env_name in server.env:
if env_name.strip().upper() in _CODE_INJECTING_ENV_VARS:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=(f"MCP server '{name}' sets environment variable '{env_name}', which would run arbitrary code at process startup."),
)
def _mask_server_config(server: McpServerConfigResponse) -> McpServerConfigResponse:
"""Return a copy of server config with sensitive fields masked.
Masks env values, header values, and removes OAuth secrets so they
are not exposed through the GET API endpoint.
"""
masked_env = {k: _MASKED_VALUE for k in server.env}
masked_headers = {k: _MASKED_VALUE for k in server.headers}
masked_oauth = None
if server.oauth is not None:
masked_oauth = server.oauth.model_copy(
update={
"client_secret": None,View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Remove the code-injecting variable from the server's env block
- Achieve the effect differently: set runtime options via launcher args, or configure the server package itself
- If a variable is genuinely required and safe, ask the operator to run that server outside the API-managed path
Example fix
# before
{"command": "npx", "args": ["-y", "srv"], "env": {"NODE_OPTIONS": "--require ./preload.js"}}
# after
{"command": "npx", "args": ["-y", "srv"], "env": {"SRV_CONFIG_PATH": "/etc/srv/config.json"}} Defensive patterns
Strategy: validation
Validate before calling
const CODE_INJECTING = new Set(['PYTHONSTARTUP','NODE_OPTIONS','LD_PRELOAD','LD_AUDIT','PERL5OPT','RUBYOPT','JAVA_TOOL_OPTIONS']);
function assertSafeEnv(env: Record<string, string>) { for (const k of Object.keys(env)) if (CODE_INJECTING.has(k.trim().toUpperCase())) throw new Error(`env var ${k} can inject startup code`); } Type guard
function isCodeInjectingEnvName(name: string): boolean { return ['PYTHONSTARTUP','NODE_OPTIONS','LD_PRELOAD','PERL5OPT','RUBYOPT','JAVA_TOOL_OPTIONS'].includes(name.trim().toUpperCase()); } Try / catch
null
Prevention
- Do not copy your local shell env into MCP server env blocks
- Express runtime tuning via launcher args or the server package's own config
- Treat any startup-hook env var as rejected by design, even for benign values
When it happens
Trigger: Submitting env: {"NODE_OPTIONS": "--require ./hook.js"} or {"PYTHONSTARTUP": "script.py"} with a stdio server; copying a Docker/env-file setup that relies on these tuning variables into MCP config.
Common situations: Legitimate-looking performance/debug tuning (NODE_OPTIONS=--max-old-space-size is still rejected as a class); hardening bypass attempts; env blocks copied from local development shells.
Related errors
- MCP server '{name}' passes '{exec_flag}' to '{command_name}'
- MCP server '{server_name}' command must be a single executab
- MCP server '{name}' uses disallowed stdio command '{command_
- Cannot set extra config key '{key}' to masked value '***'; p
- MCP server '{server_name}' with stdio transport requires a c
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/870023ea28c9864a.
Report an issue: GitHub.