Sep 19, 2026·6 min read·33 visits
Process Compose before version 1.120.0 lacks Host header, Origin header, and authentication validation on its secondary MCP SSE listener. Remote malicious websites can leverage DNS rebinding to execute arbitrary commands locally on a developer's workstation if control tools are enabled.
CVE-2026-77339 is a critical security vulnerability in Process Compose before version 1.120.0. The Model Context Protocol (MCP) Server-Sent Events (SSE) listener transport subsystem fails to validate the HTTP Host and Origin headers, and does not enforce authentication. This omissions expose local loopback listeners to DNS rebinding attacks orchestrated by malicious remote websites visited by developers, enabling unauthorized process control and arbitrary command execution.
Process Compose functions as an orchestrator and scheduler for non-containerized applications and development workloads. To facilitate integration with artificial intelligence workflows and administrative tools, the application implements the Model Context Protocol (MCP). This protocol supports bidirectional message exchange using either standard input/output (stdio) or an alternative HTTP-based Server-Sent Events (SSE) transport mechanism.
Prior to version 1.120.0, enabling the MCP SSE transport launched a separate network service that listened on a designated port. This auxiliary service exposed highly critical control capabilities to connected clients. However, this endpoint was implemented outside of the main API gateway, leaving it decoupled from the core application's access control measures.
Because the auxiliary listener processed incoming requests without verifying standard browser protection headers, it presented an exposed interface to local browser contexts. When a developer visits an external untrusted website, client-side scripts running on that site can target the exposed port. By utilizing DNS rebinding techniques, malicious parties can establish an active channel directly to the loopback interface, gaining control of Process Compose operations.
The root cause of this vulnerability lies in the transport initialization architecture within src/mcp/server.go. When starting the MCP SSE listener, the application spawned a concurrent goroutine running a third-party library's built-in web server. This secondary server did not route through the primary Gin framework engine, effectively bypassing the X-PC-Token-Key validation middleware implemented for standard REST operations.
Furthermore, the listener accepted incoming requests implicitly without evaluating the HTTP Host header. Under normal conditions, the browser's Same-Origin Policy (SOP) blocks cross-origin reading of loopback responses. However, when an attacker configures a malicious domain to rebind to 127.0.0.1, the browser perceives the local service as part of the external origin, circumventing SOP restrictions.
The application also failed to validate the HTTP Origin header. Without explicit CORS configurations or checks to verify that the incoming Origin represents a domestic hostname, the server handled all cross-origin requests. Consequently, any web page opened by the local developer could dispatch arbitrary JSON-RPC actions directly to the local server stream.
In affected versions of Process Compose, the startSSE method in src/mcp/server.go instantiated the server using a default configuration. The library-provided server lacked built-in middleware for access control and executed without an outer HTTP wrapper:
// Vulnerable implementation in src/mcp/server.go
func (s *Server) startSSE() error {
// ...
sseServer := server.NewSSEServer(s.mcpServer)
go func() {
// Bypasses all standard token-verification layers
if err := sseServer.Start(addr); err != nil {
log.Error().Err(err).Msg("MCP SSE server error")
}
}()
// ...
}The security patch introduced in version 1.120.0 wraps the sseServer in a custom http.Server configured with a dedicated middleware handler called sseSecurityMiddleware. This middleware acts as a gatekeeper that validates the structural properties of each request before passing control to the underlying handler:
// Patched security middleware in src/mcp/sse_security.go
func (s *Server) sseSecurityMiddleware(next http.Handler) http.Handler {
trusted := s.trustedHosts()
token := config.GetApiToken()
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 1. Host validation (blocks DNS rebinding)
if !hostAllowed(hostname(r.Host), trusted) {
reject(w, r, http.StatusForbidden, "untrusted host")
return
}
// 2. Origin validation (checks cross-origin requests)
if origin := r.Header.Get("Origin"); origin != "" {
u, err := url.Parse(origin)
if err != nil || !hostAllowed(hostname(u.Host), trusted) {
reject(w, r, http.StatusForbidden, "untrusted origin")
return
}
}
// 3. Enforce token validation if configured
if token != "" && !tokenValid(r, token) {
w.Header().Set("WWW-Authenticate", "Bearer")
reject(w, r, http.StatusUnauthorized, "invalid or missing token")
return
}
next.ServeHTTP(w, r)
})
}By ensuring that r.Host is strictly compared against trusted entities, the server rejects requests targeting attacker.com:8081 even if the underlying IP address resolves to 127.0.0.1. In addition, cryptographic token verification prevents unauthorized tools from communicating with the server.
To execute this attack, the victim must navigate to a malicious web page controlled by the attacker. This page serves a script that schedules background requests back to the source domain. The attacker configures a DNS nameserver with a Time-to-Live (TTL) of zero, ensuring the browser refreshes the address lookup on subsequent requests.
Upon initial resolution, the domain resolves to the attacker's web server, which supplies the payload script. During subsequent execution loops, the custom nameserver changes its response record to point directly to 127.0.0.1 on the port assigned to Process Compose (default 8081). The browser, honoring the original hostname context, allows the JavaScript payload to make cross-origin requests.
Because the vulnerable server is unauthenticated, the rebound JavaScript payload can query /sse to receive real-time streams or POST commands directly. If administrative control parameters are enabled, the payload can trigger command executions, stop local development databases, or extract environment logs containing sensitive tokens and credentials.
The impact of CVE-2026-77339 varies depending on the active configuration of the Process Compose environment. If control tools are disabled, the attacker is limited to auditing tasks. They can read and search execution logs, exposing configuration details, source code references, and runtime secrets that are printed to stdout or stderr streams.
When expose_control_tools is set to true, the impact escalates to active system disruption. The attacker can stop, restart, scale, or terminate any service orchestrated by Process Compose. This can result in complete workflow denial-of-service, leaving local pipelines non-functional.
If the deployment contains user-defined custom tools, the threat reaches critical levels. Because Process Compose tools run with the privileges of the executing system user, the attacker can use the exposed JSON-RPC boundary to run arbitrary shell commands. This achieves full remote code execution on the developer's workstation.
The standard path to remediation is upgrading local installations of Process Compose to version 1.120.0 or later. This version introduces defensive checks that block DNS rebinding attempts. The patch is considered highly effective because it implements validation checks across Host, Origin, and token boundaries.
If upgrading immediately is not possible, security teams should configure the primary application token. Setting the PC_API_TOKEN environment variable ensures that the patched middleware rejects any request lacking an authorization header. This prevents unauthenticated command exploitation even if the Host validation check is bypassed.
Additionally, developers should avoid binding the application's network listeners to the wildcard address 0.0.0.0. Restricting binding rules strictly to local interfaces like 127.0.0.1 reduces external network discoverability. Review your configuration parameters to ensure that expose_control_tools is set to false unless specifically required.
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| Product | Affected Versions | Fixed Version |
|---|---|---|
process-compose F1bonacc1 | < 1.120.0 | 1.120.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-306, CWE-346 |
| Attack Vector | Network (Requires User Interaction & DNS Rebinding) |
| CVSS v4.0 | 5.1 (Medium) |
| EPSS Score | Not yet assigned |
| Impact | Information Disclosure, Denial of Service, Remote Code Execution |
| Exploit Status | PoC / Theoretical |
| KEV Status | Not in KEV Catalog |
The application fails to authenticate critical operations and does not validate request headers to verify appropriate cross-origin restrictions.
CVE-2026-62374 (GHSA-f9j6-8p6x-r9j6) is a verification bypass vulnerability in the OpenWallet Foundation SD JWT JS library (@sd-jwt/core and @sd-jwt/decode versions 0.19.0 and earlier). Due to permissive UTF-8 decoding and the omission of mandatory reference checks during presentation verification, tampered or unreferenced disclosures are silently dropped rather than rejected. This deviates from RFC 9901 §7.1 requirements and allows attackers to execute silent claim-set reduction attacks against relying parties.
An interpretation conflict in Bytebase DBHub (< 0.22.6) allows attackers to bypass read-only SQL query restrictions when connected to MySQL or MariaDB instances. Because DBHub's custom SQL tokenizer treats any '--' sequence as a comment, whereas MySQL and MariaDB require trailing whitespace or a control character, crafted queries containing '--' immediately followed by non-whitespace characters allow stacked destructive SQL statements to execute on connections configured as read-only.
CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.
CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.
CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).
CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.