Skip to content

[security] Fix unauthenticated MCP config disclosure and stdio process execution#1646

Open
13ernkastel wants to merge 16 commits intobytedance:mainfrom
13ernkastel:fix-mcp-management-rce
Open

[security] Fix unauthenticated MCP config disclosure and stdio process execution#1646
13ernkastel wants to merge 16 commits intobytedance:mainfrom
13ernkastel:fix-mcp-management-rce

Conversation

@13ernkastel
Copy link
Copy Markdown
Contributor

@13ernkastel 13ernkastel commented Mar 31, 2026

Summary

This PR fixes a security vulnerability in DeerFlow's MCP management API.

Before this change, /api/mcp/config returned raw MCP server configuration, including sensitive fields such as env, headers, and OAuth credentials, and also allowed arbitrary transport configuration to be overwritten over HTTP. DeerFlow would later consume that attacker-controlled configuration during MCP tool initialization and start the supplied stdio process.

As a result, the MCP settings API was not just a UI configuration surface: it exposed a path to unauthenticated secret disclosure and backend process execution.

Impact

  • unauthenticated disclosure of MCP secrets and credentials
  • unauthenticated backend process execution through attacker-controlled stdio MCP rewrites
  • likely host-level compromise in the default Docker deployment because the shipped stack mounts /var/run/docker.sock and includes Docker tooling in the backend image

CVSS Estimate

Estimated CVSS v3.1 base score: 9.8 (Critical)

Vector:

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Rationale:

  • AV:N: reachable over the network through the exposed HTTP API
  • AC:L: no unusual race, brute force, or environmental precondition is required once the API is reachable
  • PR:N: no authentication is required
  • UI:N: no victim interaction is required
  • S:U: the direct impact is on the DeerFlow backend runtime itself
  • C:H/I:H/A:H: the issue exposes secrets and enables attacker-controlled process execution, which can fully compromise confidentiality, integrity, and availability of the backend service

The shipped Docker deployment can make the practical impact even worse because backend code execution may be chained into host-level Docker control via the mounted Docker socket.

Benign PoC

Because this PR is public, the PoC below is intentionally non-destructive.

1. Read secret-bearing MCP config over HTTP

curl http://localhost:2026/api/mcp/config

Pre-fix response shape:

{
  "mcp_servers": {
    "github": {
      "enabled": true,
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "..."
      },
      "description": "GitHub operations"
    }
  }
}

2. Rewrite an existing MCP server to a benign stdio payload

curl -X PUT http://localhost:2026/api/mcp/config \
  -H "Content-Type: application/json" \
  -d '{
    "mcp_servers": {
      "github": {
        "enabled": true,
        "type": "stdio",
        "command": "/bin/sh",
        "args": ["-c", "echo deerflow-poc > /tmp/deerflow_mcp_poc.txt; sleep 1"],
        "description": "attacker controlled"
      }
    }
  }'

On the next MCP tool initialization / agent run, DeerFlow would load that rewritten config and attempt to launch the configured stdio process. In local validation, a benign marker file was created before MCP initialization failed, which confirms that the attacker-controlled process was started.

Fix

This patch removes the exploit primitives from the HTTP management surface while keeping the MCP settings UI functional:

  • return only the public MCP summary: enabled and description
  • accept only enabled-state toggles for existing MCP servers
  • preserve raw extensions_config.json transport definitions and env placeholders on disk
  • reject unknown MCP server names instead of silently creating or rewriting arbitrary definitions
  • align the backend make test entrypoint with the workspace layout so the MCP regression tests run correctly in CI/local validation

Why This Helps

This fix breaks the verified chain at the management boundary:

  • the HTTP read path no longer exposes raw transport config or secrets
  • the HTTP write path no longer allows attacker-controlled stdio command rewrites
  • normal UI toggles no longer risk rewriting resolved secrets back into the config file

After this change, the MCP settings API is no longer a remote transport editor for local process execution.

Further Hardening

  • add authentication and authorization around management APIs
  • avoid exposing /api/mcp/config directly through production-facing reverse proxies without an authenticated admin boundary
  • add audit logging for configuration changes
  • consider stricter validation or allowlisting for trusted MCP transport definitions
  • re-evaluate the default Docker posture, especially the Docker socket mount, because it magnifies the impact of any backend code-execution bug

Validation

cd backend
UV_CACHE_DIR=.uv-cache UV_TOOL_DIR=.uv-tools make lint
CI=1 UV_CACHE_DIR=.uv-cache UV_TOOL_DIR=.uv-tools make test

Result:

1195 passed, 15 skipped

Acknowledgment

Also credit @YuvalElbar6 for independently highlighting and privately reporting the same issue based on her own research. She separately submitted a duplicate CVE request before noticing this public PR, then promptly confirmed the duplicate. There is no public issue to link because her report was submitted through a private security channel.

@13ernkastel 13ernkastel changed the title [codex] Restrict MCP config API to safe toggles [security] Prevent unauthenticated MCP config disclosure and stdio RCE Mar 31, 2026
@13ernkastel 13ernkastel changed the title [security] Prevent unauthenticated MCP config disclosure and stdio RCE [security] Fix unauthenticated MCP config disclosure and stdio process execution Mar 31, 2026
@13ernkastel 13ernkastel marked this pull request as ready for review March 31, 2026 01:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens DeerFlow’s MCP management surface by preventing the gateway/client APIs from exposing or accepting secret-bearing transport configuration, reducing the risk of unauthenticated secret disclosure and attacker-controlled stdio process execution.

Changes:

  • Restricts /api/mcp/config read responses to a public summary (enabled, description) only.
  • Restricts /api/mcp/config writes to enabled-state toggles for existing MCP servers, preserving raw on-disk transport/env placeholder fields.
  • Adds focused backend regression tests and updates the backend test PYTHONPATH so MCP-related tests run reliably.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
frontend/src/app/mock/api/mcp/config/route.ts Updates mock API output to match new “public summary only” MCP response shape.
backend/tests/test_mcp_router.py Adds router-level tests verifying summary-only GET, safe PUT toggles, and unknown-server rejection.
backend/tests/test_client.py Updates client unit tests to match new enabled-toggle-only semantics and summary responses.
backend/tests/test_client_e2e.py Updates e2e tests to validate summary-only MCP reads and safe enabled-state writes.
backend/packages/harness/deerflow/mcp/management.py Introduces safe management helpers: summarization + enabled-state-only atomic persistence.
backend/packages/harness/deerflow/mcp/init.py Exports new MCP management helpers at package level.
backend/packages/harness/deerflow/client.py Switches client MCP APIs to summary-only reads and enabled-toggle-only updates.
backend/Makefile Adjusts make test PYTHONPATH to include packages/harness for test execution.
backend/docs/API.md Updates API docs to reflect summary-only GET and enabled-toggle-only PUT behavior.
backend/app/gateway/routers/mcp.py Refactors gateway endpoints/models to only expose public MCP summary and accept enabled toggles.

Comment thread backend/packages/harness/deerflow/mcp/management.py
Comment thread backend/packages/harness/deerflow/client.py
Comment thread backend/app/gateway/routers/mcp.py
Comment thread backend/packages/harness/deerflow/client.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants