Skip to content

Sandbox workers start without -I and can import mcp_server from PYTHONPATH or the working directory #146

Open

Description

@ViperJuice

Summary

In 1.6.0, sandboxed plugin workers start without Python's isolated mode. They inherit the parent's environment and working directory. A worker can therefore import mcp_server from PYTHONPATH, from the user site, or from its working directory instead of from the installed package. This happens even when the parent server itself runs under python -I.

Where

  • mcp_server/plugins/sandboxed_plugin.py builds the worker command as [sys.executable, "-m", "mcp_server.sandbox.worker_main", ...].
  • mcp_server/sandbox/supervisor.py starts it with subprocess.Popen(...), passing no env= and no cwd=.
  • The sandbox is on by default (unless MCP_PLUGIN_SANDBOX_DISABLE=1).

Why it matters

MCP clients usually start the server in the project directory. With -m, the worker puts its working directory first on sys.path. Indexing a checkout that has a top-level mcp_server/ would then run that checkout's code as the user instead of the pinned worker. Examples are a hostile repository or this project's own source tree. An inherited PYTHONPATH has the same effect. Running the top-level server under python -I does not help, because -I is not passed on to the child process.

This reproduces with a minimal stand-in that starts its worker exactly as above. A hostile PYTHONPATH, or a working directory holding a hostile mcp_server/, replaces the worker. A clean environment does not.

Suggested fix

  • Start workers with the parent's isolation flags. For example, use [sys.executable, "-I", "-B", "-m", "mcp_server.sandbox.worker_main", ...], or at least -P -s when -I is not wanted.
  • And/or pass an explicit env= that drops PYTHON* variables, plus a neutral cwd=.
  • Add a regression test: start the server with a hostile PYTHONPATH and working directory, and check that the worker imports the installed package.

Downstream mitigation

The Consiliency shared tooling launcher now clears PYTHON* variables and sets PYTHONSAFEPATH=1, PYTHONNOUSERSITE=1 and PYTHONDONTWRITEBYTECODE=1 before starting the server, so workers inherit safe settings. See Consiliency/dotfiles#272. A fix here would protect every other launcher too.

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