Skip to content

MCP expand_env_vars reads any env var into argv — leaks daemon secrets via /proc/cmdline #3823

Description

@houko

Summary

Before spawning an MCP server, expand_env_vars substitutes $VAR references in argv from the daemon's full process environment with no allowlist. The expanded values land on the child's argv, which is visible in ps, /proc/<pid>/cmdline, system audit logs, and crash dumps.

Evidence

  • crates/librefang-runtime-mcp/src/lib.rs:1006let args_owned: Vec<String> = args.iter().map(|a| expand_env_vars(a)).collect();
  • crates/librefang-runtime-mcp/src/lib.rs:2118else if let Ok(val) = std::env::var(&var_name) { result.push_str(&val); } (no allowlist)
  • Compare :1015 cmd.env_clear() and :1018 for &var in SAFE_ENV_VARS — env passed to child is correctly allowlisted; argv expansion is not.

Why it's a bug (attack)

Anyone able to register an MCP server (admin, dashboard caller, [[mcp_servers]] template) configures args = ["--token", "$LIBREFANG_VAULT_KEY"] or "$ANTHROPIC_API_KEY". The daemon expands them and places the secret on argv. The whole point of env_clear() + SAFE_ENV_VARS was to deny the child the daemon environment; argv expansion reopens that hole on a far worse channel — argv leaks beyond the subprocess into every observability layer.

Proposed fix

Restrict expand_env_vars to the same SAFE_ENV_VARS allowlist (or to names declared in extra_env); for any other reference, leave the literal $VAR text untouched and log a warning. Alternatively, drop arg-side expansion entirely and require operators to set values through extra_env.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/runtimeAgent loop, LLM drivers, WASM sandboxarea/securitySecurity systems and auditingbugSomething isn't workingdifficulty/easy1-3 hours, minimal context neededneeds-triageAuto-applied when the issue title/body matched no area label — needs maintainer reviewsecuritySecurity issuesseverity/criticalRemote-exploitable, data loss, or production-blocking

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions