Sep 15, 2026·9 min read·50 visits
Unauthenticated remote attackers can bypass Same-Origin Policy via DNS Rebinding to execute commands and access data through the local GitLab MCP server due to missing Host and Origin header validation.
A critical security vulnerability has been identified in the @zereight/mcp-gitlab implementation of the Model Context Protocol (MCP) server. Prior to version 2.1.30, the server lacks HTTP Host and Origin header validation on its Streamable HTTP transport interface (/mcp). This security omission permits remote attackers to bypass the Same-Origin Policy (SOP) via a DNS Rebinding attack. Under this vector, an attacker can route malicious API requests to the victim's local or internal MCP server, thereby gaining unauthorized control over the victim's GitLab account and resources.
The Model Context Protocol (MCP) defines an open standard for secure bidirectional communication between local Large Language Model (LLM) applications and remote or local data sources, systems, and APIs. In the context of the @zereight/mcp-gitlab server, this integration allows developer agents to query, create, or alter repositories, branch setups, pull requests, issues, and pipelines. To facilitate browser-based tool interactions or integration within local containerized orchestrations, the @zereight/mcp-gitlab server implements a Streamable HTTP transport endpoint located at /mcp. This HTTP listener executes locally on a loopback interface, commonly on a user-specified port or default range, and operates using the target user's local operating system identity and GitLab credentials.
Historically, developer tools operating on loopback interfaces have relied upon the browser's Same-Origin Policy (SOP) to block malicious external websites from querying local socket endpoints. However, because the SOP restricts access based on the hostname of the origin rather than the underlying network socket's IP destination, local endpoints must explicitly validate incoming routing metadata. In versions of @zereight/mcp-gitlab prior to 2.1.30, the Express-based Streamable HTTP server fails to perform verification checks on the standard Host and Origin HTTP request headers. This failure exposes a critical attack surface, as any HTTP client capable of reaching the TCP socket can interact with the API interface.
The class of this flaw is classified under CWE-350 (Reliance on Reverse DNS Resolution for a Security-Critical Action), specifically materializing as a DNS Rebinding vulnerability. An attacker can leverage this flaw by executing arbitrary code inside the context of a victim's web browser, bridging the boundary from an untrusted public domain to the victim's local loopback domain. Because the MCP server stores sensitive, high-privilege credentials—such as personal access tokens, job tokens, or active authentication cookies—the target's GitLab instance can be completely compromised by an unauthenticated remote adversary. This threat vector bypasses firewall boundaries and physical segmentations by abusing the victim's browser as a trusted network proxy.
The fundamental technical flaw in the Streamable HTTP transport implementation lies in the lack of request-filtering middleware at the HTTP routing boundary. When the application initializes its server interface using the Express framework, it configures routes such as /mcp without binding any policy check to verify if the requested Host header aligns with the intended deployment address. In a standard web browser context, the Same-Origin Policy prevents an active script executing under https://attacker.com from dispatching a request to http://localhost:3002 and reading the response. However, the browser delegates name resolution to the underlying DNS subsystem, creating a synchronization gap that can be exploited via DNS Rebinding.
In a typical DNS Rebinding scenario, an attacker provisions an authoritative nameserver for a domain they control, such as rebinder.attacker.test. The nameserver is configured with a Time-To-Live (TTL) value of 0 seconds to prevent caching. When the victim browser navigates to the attacker's domain, the authoritative server returns the actual IP address of the attacker's web server. The browser loads the malicious payload page, establishes an origin context of http://rebinder.attacker.test, and begins executing malicious JavaScript. The malicious script then initiates a background XMLHttp or Fetch request back to its parent domain, pointing to the /mcp endpoint.
As the DNS TTL is set to 0, the browser must re-resolve rebinder.attacker.test to process the new connection. At this step, the attacker's DNS server answers with the loopback IP address 127.0.0.1. The browser, strictly adhering to the name-based SOP, permits the request because the origin hostname rebinder.attacker.test remains unchanged. The browser dispatches the HTTP request directly to 127.0.0.1:3002. The request arrives at the local @zereight/mcp-gitlab server, bearing the headers Host: rebinder.attacker.test and Origin: http://rebinder.attacker.test. Prior to the implementation of the patch, the server processed this payload without validation, interpreting the request as a valid client connection and executing the embedded JSON-RPC payload.
The vulnerability was resolved in Pull Request #555 with the commit 52207c6f5c0e7a39e9235d491225edbb562a0290. The fix introduces an active validation middleware function, requireMcpHostAndOrigin, inside the primary server configuration file. This middleware extracts, normalizes, and compares the incoming HTTP headers against an explicitly parsed and configured allowlist of hosts and origins.
Let us analyze the critical validation function implemented to protect the server:
function requireMcpHostAndOrigin(req: Request, res: Response, next: NextFunction) {
const host = toAllowedMcpHost(req.headers.host || "");
if (
!host ||
(!isLoopbackMcpHost(host) && !MCP_DNS_REBINDING_PROTECTION.allowedHosts.includes(host))
) {
res.status(403).json({
error: "Host header is not allowed",
hint: "Set MCP_SERVER_URL or MCP_ALLOWED_HOSTS for non-loopback /mcp hosts.",
});
return;
}
const originHeader = req.headers.origin;
if (originHeader) {
const origin = toAllowedMcpOrigin(Array.isArray(originHeader) ? originHeader[0] : originHeader);
if (
!origin ||
(!isLoopbackMcpOrigin(origin) &&
!MCP_DNS_REBINDING_PROTECTION.allowedOrigins.includes(origin))
) {
res.status(403).json({
error: "Origin header is not allowed",
hint: "Set MCP_SERVER_URL or MCP_ALLOWED_ORIGINS for non-loopback browser origins.",
});
return;
}
}
next();
}The middleware intercepts incoming requests to /mcp prior to any JSON parsing or JSON-RPC handling. The logic utilizes Node's WHATWG URL parser to extract hostnames safely, which protects against URL parsing bypasses where characters like @ or special port indicators are manipulated. It establishes a loopback exception where any requests routing to localhost, 127.0.0.1, or [::1] on any port are automatically approved. This exception is secure because an attacker executing a DNS Rebinding attack must point the browser to their arbitrary domain, which forces the Host header to hold the attacker's domain value rather than a loopback string. The patch is applied to the application route hierarchy as follows:
app.use("/mcp", requireMcpHostAndOrigin);
app.use(express.json());This mounting order ensures that validation occurs before JSON parsing, which prevents CPU cycles from being consumed on unauthenticated payloads. If either the Host or Origin check fails, the middleware aborts the request pipeline immediately, returning an HTTP 403 Forbidden status.
Exploitation of CVE-2026-61568 is highly reliable and relies on a target user running a vulnerable version of the server locally while browsing the web. The attacker initiates the exploitation cycle by registering a target domain and configuring a custom authoritative DNS server capable of dynamically toggling A record responses. Once the victim is induced to visit the attacker-controlled webpage, the malicious site serves a payload designed to loop requests.
The payload script implements a standard asynchronous loop that sends HTTP POST requests containing MCP initialization payloads to the target local port (typically standard development ports). The request format resembles the following JSON-RPC schema:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": {
"name": "malicious-agent",
"version": "1.0.0"
}
}
}The integration test suite located in test/streamable-http-dns-rebinding.test.ts provides a clear proof-of-concept. It spins up the server dynamically and sends requests with forged Host and Origin headers to simulate the DNS Rebinding behavior. The tests assert that the patched server rejects headers containing domains such as attacker.example.test with an HTTP 403 response, while still allowing legitimate remapped Docker ports originating from loopback hosts. By evaluating this test, security engineers can confirm that the mitigation successfully breaks the DNS Rebinding vector without impairing valid developer configurations.
The security impact of CVE-2026-61568 is critical, as reflected by its CVSS 3.1 base score of 9.6. Because the MCP server operates in a scope that bridges the local browser interface to the corporate GitLab API, the vulnerability results in a Change (S:C) of security boundaries. This allows an attacker to leverage the victim's authorization state on the GitLab server.
If the victim possesses administrative access or access to proprietary codebases, the impact translates to a complete loss of confidentiality and integrity. The malicious JavaScript payload running in the browser can execute JSON-RPC commands on the local MCP server to read raw source code repositories, download sensitive environment configuration files, manipulate pipeline variables, and inject malicious commits directly into protected branches. Furthermore, the attacker can leverage the server to approve merge requests, trigger deployment pipelines to expose production secrets, or delete critical repository data, which completely compromises the availability of the organization's DevOps infrastructure.
The attack vector is purely remote and requires no active privileges on the part of the attacker, though it requires minimal user interaction to entice the victim to load the initial malicious website. Because the vulnerability targets developers who frequently run local tools with active, high-privilege access keys, a successful compromise can serve as a vector for supply chain attacks against downstream software products.
To completely remediate CVE-2026-61568, administrators and developers must update @zereight/mcp-gitlab to version 2.1.30 or higher immediately. This update enforces the Host and Origin validation middleware by default. The update can be performed through npm or equivalent package managers using the command:
npm install @zereight/mcp-gitlab@latestIf the server must be deployed in non-loopback topologies—such as behind a reverse proxy, inside an orchestrator network like Kubernetes, or on an internal corporate network address—administrators must configure explicit environmental configurations to allow authorized traffic. The server reads these configurations from environment variables at startup. To declare these safe domains, define MCP_SERVER_URL with the server's public URL, or define MCP_ALLOWED_HOSTS and MCP_ALLOWED_ORIGINS with comma-separated lists of acceptable hosts and origins. For example:
export MCP_SERVER_URL="https://mcp.internal.net"
export MCP_ALLOWED_HOSTS="mcp.internal.net,mcp.internal:3002"
export MCP_ALLOWED_ORIGINS="https://mcp.internal.net,http://localhost:3000"For systems that cannot be immediately updated, temporary workarounds include blocking access to the MCP server port from external network interfaces using local firewall rules (e.g., binding the application socket strictly to 127.0.0.1 rather than 0.0.0.0) and restricting developers from visiting untrusted external websites while the local server is active.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
@zereight/mcp-gitlab zereight | < 2.1.30 | 2.1.30 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-350 |
| Attack Vector | Network |
| CVSS Score | 9.6 |
| EPSS Score | Not Available |
| Impact | Complete Confidentiality, Integrity, and Availability Loss |
| Exploit Status | poc |
| KEV Status | Not Listed |
The software relies on reverse DNS resolution to perform a security-critical action, which can allow attackers to bypass security checks.
An OS command injection and argument injection vulnerability exists in the Nx build system and its official Maven (@nx/maven) and Gradle (@nx/gradle) plugins. When constructing the project dependency graph, the plugins invoke underlying Java build wrappers via subshells while interpolating unsanitized plugin options directly from nx.json into the command arguments. An attacker who supplies a crafted nx.json file via a repository or pull request can execute arbitrary shell commands with the privileges of the user or CI/CD runner invoking any Nx command that computes the project graph.
AdminNeo versions 4.6.2 through 5.4.1 contain an improper input validation vulnerability (CWE-20) in the version verification endpoint (?script=version). An unauthenticated remote attacker can submit a crafted HTTP POST request containing an array parameter for 'version', which is serialized into a shared server-side temporary cache file without type checking or authentication. On subsequent requests, the application deserializes this cached array and passes it to cookie() and rawurlencode(), triggering an uncaught fatal TypeError in PHP 8.x environments and causing a persistent 24-hour Denial of Service (DoS) for all users.
Charmbracelet Soft Serve versions 0.5.0 through 0.12.2 contain an authorization bypass and observable response discrepancy vulnerability in the HTTP Git server. Remote attackers can determine the existence, exact names, and clone URLs of private repositories by issuing crafted Go remote import path discovery requests (?go-get=1) or by observing differential HTTP status codes across Git Smart HTTP, Dumb HTTP, and Git LFS endpoints.
A Time-of-Check to Time-of-Use (TOCTOU) race condition in Charmbracelet Soft Serve versions 0.6.0 through 0.12.2 allows unauthenticated users to retain read access to repositories after their visibility is changed from public to private. The flaw stems from premature cache invalidation in the SetPrivate method prior to committing the visibility update to the underlying database. Concurrent read requests arriving during the database transaction window repopulate the non-expiring in-memory LRU cache with stale public metadata, bypassing access controls across HTTP, SSH, and Git protocols until the server process is restarted.
A resource consumption vulnerability exists in the Authlib joserfc Python library prior to version 1.7.5. When processing JSON Web Encryption (JWE) objects formatted using General JSON Serialization, the library fails to enforce an upper bound on the number of elements within the recipients array. An unauthenticated attacker can supply a JWE containing thousands of recipient entries targeting an RSA key management algorithm, forcing the server to perform an equivalent number of computationally expensive RSA private-key decryption operations per request and exhausting available CPU resources.
CVE-2026-119284 (GHSA-9pg5-8c7x-5hfx) is an uncontrolled resource consumption vulnerability (CWE-400) in the compact serialization deserialization routines of joserfc prior to version 1.7.6. The library enforced individual segment size limits only after invoking Python's bytes.split(b'.') on untrusted input tokens. By sending oversized compact JWS or JWE tokens, an unauthenticated remote attacker can force the Python interpreter to duplicate and allocate memory for every segment before size validation executes, resulting in memory exhaustion and an Endpoint Denial of Service (DoS).