Skip to content

[feat]: Let users extend the agent env allowlist (MCP credentials referenced as ${VAR} are stripped) #3103

Description

@felixgabler

Feature Summary

Let users extend the environment allowlist that Emdash applies when it spawns an agent (or opt in to inheriting the login shell environment), so credentials that MCP configs reference as ${VAR} reach the agent.

Problem or Use Case

buildAllowlistedAgentEnv (packages/core/src/primitives/agent-env/api/index.ts) builds the agent process env from fixed lists (AGENT_ENV_VARS, GLOBAL_AGENT_ENV_VARS, DISPLAY_ENV_VARS, plus PATH/HOME/TMPDIR/SSH_AUTH_SOCK). Nothing else from the host environment is passed through, and there is no setting to add names.

Our team repo generates .mcp.json / .cursor/mcp.json / .codex/config.toml with entries like "Authorization": "Bearer ${SUPABASE_ACCESS_TOKEN}" and bearer_token_env_var = "LINEAR_PAT". Those variables live in each developer's ~/.zshenv. In a terminal, Claude Code and Codex connect fine. Spawned from Emdash 1.2.2, every ${VAR} expands to an empty string and all credentialed MCP servers fail with 401 (JWT could not be decoded, Authorization header is badly formatted, ...). The Bash tool inside the agent still sees the variables because it runs through the user's zsh, which makes the failure confusing to diagnose.

The allowlist is a sensible default for not leaking secrets into worktrees, but the whitelisted set is vendor keys only. Anyone who wires MCP servers through env-referenced tokens hits this.

Proposed Solution

One of:

  1. A host setting (and .emdash.json key) with extra env var names to pass through, e.g. agentEnvPassthrough: ["SUPABASE_ACCESS_TOKEN", "LINEAR_PAT"], merged into the allowlist by name only. Values are never stored by Emdash.
  2. An opt-in toggle "inherit login shell environment" that runs the provider through $SHELL -lc (or sources the user's shell env) before exec.

Alternatives Considered

  • Per-provider "Environment variables" in Settings works but requires pasting every secret value into Emdash, per developer, and keeping it in sync on rotation.
  • Workaround we are using now: .emdash.json shellSetup: "[ -f \"$HOME/.zshenv\" ] && . \"$HOME/.zshenv\" || true". Because a non-empty shellSetup makes resolvePosixSpawn wrap the agent in <shell> -c "<setup> && <agent>", the sourced variables reach the agent. It works, but it is undocumented behaviour of a field meant for nvm use, and it silently re-opens the whole environment rather than a named set.

emdash Version

v1.2.2 (macOS 26.6, zsh)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions