Every CVE Search/ Get API key

CVE-2026-55786

Flyto2 Core: Unauthenticated Command Execution via HTTP MCP `execute_module`

8.4 HighFix available

Flyto2 Core is an execution kernel for automation and AI-agent workflows. From 2.26.2 until 2.26.4, the HTTP MCP POST /mcp route accepts unauthenticated JSON-RPC tools/call requests and forwards execute_module arguments to the module registry without the require_auth dependency used by the REST execution routes. An unauthenticated caller can select sandbox.execute_shell and supply its command parameter, which reaches asyncio.create_subprocess_shell with the privileges of the flyto-core server process. The endpoint is reachable locally under the default loopback binding and becomes network reachable when an operator binds the server to a non-loopback interface, allowing arbitrary OS command execution and potential full host compromise. This issue is fixed in version 2.26.4.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

Exploit likelihood

0.41%Up 0.2 points since Oct 15, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.4

Flyto2 Core: Unauthenticated Command Execution via HTTP MCP `execute_module`

Flyto2 Core is an execution kernel for automation and AI-agent workflows. From 2.26.2 until 2.26.4, the HTTP MCP POST /mcp route accepts unauthenticated JSON-RPC tools/call requests and forwards execute_module arguments to the module registry without the require_auth dependency used by the REST execution routes. An unauthenticated caller can select sandbox.execute_shell and supply its command parameter, which reaches asyncio.create_subprocess_shell with the privileges of the flyto-core server process. The endpoint is reachable locally under the default loopback binding and becomes network reachable when an operator binds the server to a non-loopback interface, allowing arbitrary OS command execution and potential full host compromise. This issue is fixed in version 2.26.4.

Record
CVE-2026-55786
CVSS 3.1
8.4 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-78, CWE-306
Updated
2026-11-02
EUVDEUVD-2026-101589 8.4

Flyto2 Core is an execution kernel for automation and AI-agent workflows. From 2.26.2 until 2.26.4, the HTTP MCP POST /mcp route accepts unauthenticated JSON-RPC tools/call requests and forwards execute_module arguments to the module registry without the require_auth dependency used by the REST execution routes. An unauthenticated caller can select sandbox.execute_shell and supply its command parameter, which reaches asyncio.create_subprocess_shell with the privileges of the flyto-core server process. The endpoint is reachable locally under the default loopback binding and becomes network reachable when an operator binds the server to a non-loopback interface, allowing arbitrary OS command execution and potential full host compromise. This issue is fixed in version 2.26.4.

Record
EUVD-2026-101589
CVSS 3.1
8.4 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-h9f9-h6gm-wc85 8.4

flyto-core has Unauthenticated Command Execution via HTTP MCP `execute_module`

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:

# src/core/api/routes/mcp.py:65-66  — missing auth
@router.post("")
async def mcp_post(request: Request):
# 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,
    )
# 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:

# 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):

# Build the image (context: the report directory containing repo/ and vuln-001/)
docker build \
  -f…
Record
GHSA-h9f9-h6gm-wc85
CVSS 3.1
8.4 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-78, CWE-306
Updated
2026-11-02
NVD 8.4

Flyto2 Core is an execution kernel for automation and AI-agent workflows. From 2.26.2 until 2.26.4, the HTTP MCP POST /mcp route accepts unauthenticated JSON-RPC tools/call requests and forwards execute_module arguments to the module registry without the require_auth dependency used by the REST execution routes. An unauthenticated caller can select sandbox.execute_shell and supply its command parameter, which reaches asyncio.create_subprocess_shell with the privileges of the flyto-core server process. The endpoint is reachable locally under the default loopback binding and becomes network reachable when an operator binds the server to a non-loopback interface, allowing arbitrary OS command execution and potential full host compromise. This issue is fixed in version 2.26.4.

Record
CVE-2026-55786
CVSS 3.1
8.4 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-78, CWE-306
Updated
2026-11-02
OSV 8.4

Flyto2 Core: Unauthenticated Command Execution via HTTP MCP `execute_module`

Flyto2 Core is an execution kernel for automation and AI-agent workflows. From 2.26.2 until 2.26.4, the HTTP MCP POST /mcp route accepts unauthenticated JSON-RPC tools/call requests and forwards execute_module arguments to the module registry without the require_auth dependency used by the REST execution routes. An unauthenticated caller can select sandbox.execute_shell and supply its command parameter, which reaches asyncio.create_subprocess_shell with the privileges of the flyto-core server process. The endpoint is reachable locally under the default loopback binding and becomes network reachable when an operator binds the server to a non-loopback interface, allowing arbitrary OS command execution and potential full host compromise. This issue is fixed in version 2.26.4.

Record
CVE-2026-55786
CVSS 3.1
8.4 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-306, CWE-78
Updated
2026-11-02
OSVGHSA-h9f9-h6gm-wc85 8.4

flyto-core has Unauthenticated Command Execution via HTTP MCP `execute_module`

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:

# src/core/api/routes/mcp.py:65-66  — missing auth
@router.post("")
async def mcp_post(request: Request):
# 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,
    )
# 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:

# 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):

# Build the image (context: the report directory containing repo/ and vuln-001/)
docker build \
  -f…
Record
GHSA-h9f9-h6gm-wc85
CVSS 3.1
8.4 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-306, CWE-78
Updated
2026-11-02
OSVPYSEC-2026-2482 8.4

flyto-core has Unauthenticated Command Execution via HTTP MCP `execute_module`

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:

# src/core/api/routes/mcp.py:65-66  — missing auth
@router.post("")
async def mcp_post(request: Request):
# 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,
    )
# 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:

# 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):

# Build the image (context: the report directory containing repo/ and vuln-001/)
docker build \
  -f…
Record
PYSEC-2026-2482
CVSS 3.1
8.4 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
flyto-core
PyPI
2.26.2 up to 2.26.4
2.26.4
flyto-core
PyPI
2.26.2 up to 2.26.4, plus listed versions
2.26.3
2.26.4

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-55786 is a high vulnerability (CVSS 8.4) in Flytohub Flyto-core, published July 6, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.41%, the 35th percentile. Fixed in flyto-core 2.26.4.

References

This page doesn't list everything

Left out here: the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open