dns-rebinding-protection: check Host and Origin validation separately
Los mantenedores suelen responder en 4 días
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 45/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- typescript
- Área
- security, testing-qa
Línea de trabajo
Start with the commented constants in src/scenarios/server/dns-rebinding.ts and the existing dns-rebinding-protection checks. Read the fixture files dns-rebinding-host-only.ts, dns-rebinding-origin-only.ts, and no-dns-rebinding-protection.ts, then inspect negative.test.ts. Done means Host-only and Origin-only requests are checked separately, the fixture schema issue is corrected, and the listed server results are asserted.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Gap
localhost-host-rebinding-rejected sends Host: evil.example.com and Origin: http://evil.example.com in the same request and passes on any 4xx. A server that validates only one of the two headers passes it.
The two headers are separate defenses:
Hostis wrong on every rebound request, including the same-origin GET that opens the SSE stream, which carries noOrigin. The SDK advisories (GHSA-w48q-cv73-mx4w, GHSA-9h52-p55h-vw2f) were fixed by validatingHoston localhost.Originis what the transport spec requires, with a fixed status code.
So the scenario cannot tell whether a server meets the Origin MUST, and it cannot tell whether a server validates Host.
Example: the everything-server in this repo uses createMcpExpressApp() from @modelcontextprotocol/sdk 1.29, which validates Host only. With a localhost Host and Origin: http://evil.example.com it returns 200, and it passes the current scenario 2/2.
Spec text
Streamable HTTP, draft ("Security & Endpoint"), and the same wording in 2025-11-25 ("Security Warning"):
- Servers MUST validate the
Originheader on all incoming connections to prevent DNS rebinding attacks.
- If the
Originheader is present and invalid, servers MUST respond with HTTP 403 Forbidden. The HTTP response body MAY comprise a JSON-RPC error response that has noid.
- draft: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ab3a39c13bd23be691c2760e1c6c5c15a64582e1/docs/specification/draft/basic/transports/streamable-http.mdx#L54-L68
- 2025-11-25: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/ab3a39c13bd23be691c2760e1c6c5c15a64582e1/docs/specification/2025-11-25/basic/transports.mdx#L74-L84
The 403 sentence came from modelcontextprotocol/modelcontextprotocol#1439. No spec text requires Host validation.
Proposal
Add two checks to the existing dns-rebinding-protection scenario. No new scenario. localhost-host-rebinding-rejected and localhost-host-valid-accepted keep their ids and behavior.
| Check | Request | Pass | Miss |
|---|---|---|---|
localhost-host-only-rebinding-rejected |
Host: evil.example.com, no Origin |
any 4xx | WARNING |
localhost-origin-only-rebinding-rejected |
localhost Host, Origin: http://evil.example.com |
exactly 403 | FAILURE |
The Origin check is FAILURE because both sentences above are MUST. The Host check is WARNING because there is no spec keyword behind it. If you would rather it be FAILURE (the scenario text already says "MUST validate the Host or Origin header") or INFO, that is a one-line change.
modelcontextprotocol/modelcontextprotocol#3370
#3370 (open, labeled bug) proposes changing this text: Host validation MUST for servers that grant access by network position, Origin validation MUST only when ambient credentials are accepted and SHOULD otherwise, 403 unchanged when a server does validate Origin. As of 2026-09-27 it has no maintainer reply and no linked spec PR. The Streamable HTTP file on main last changed in 4d260f4 (2026-08-21), and the Security section reads as quoted above.
The expected status (403) and the two miss severities are three constants in one commented block in src/scenarios/server/dns-rebinding.ts. If #3370 lands as proposed, the change is: Host miss WARNING to FAILURE, Origin miss FAILURE to WARNING, 403 unchanged.
Pass and fail examples
Results at 2025-11-25:
| Server | combined | Host-only | Origin-only | valid accepted |
|---|---|---|---|---|
| everything-server with an added Origin check | SUCCESS | SUCCESS | SUCCESS | SUCCESS |
| everything-server as on main (Host only) | SUCCESS | SUCCESS | FAILURE (200) | SUCCESS |
new dns-rebinding-host-only.ts |
SUCCESS | SUCCESS | FAILURE (200) | SUCCESS |
new dns-rebinding-origin-only.ts |
SUCCESS | WARNING (200) | SUCCESS | SUCCESS |
no-dns-rebinding-protection.ts |
FAILURE | WARNING | FAILURE | SUCCESS |
The branch adds the Origin check to the everything-server so it stays green, adds the two fixtures, and asserts each row in negative.test.ts.
Against real SDK conformance servers (conformance sdk ... --mode server --scenario dns-rebinding-protection):
- python-sdk main (f1b6589): 4/4 pass. Its localhost default validates both headers and returns 421 for
Host, 403 forOrigin. - typescript-sdk v1.x (289ac2c, 1.30.1): 3/4. The Origin-only check fails with 200; its conformance server uses
localhostHostValidation()only. It would need a fix or a baseline entry. The v2 conformance server on main uses the same middleware; I have not run it.
Related fixture bug
no-dns-rebinding-protection.ts declares inputSchema: { message: { type: 'string' } }, which SDK 1.29 rejects, so the fixture returns 500 for every request. The existing negative test passes on that 500, not on the missing protection. The branch switches it to z.string(); after that it returns 200 to the forged request and the check fails for the right reason.
- Lenguaje dominante
- TypeScript
- Estrellas
- 127
- Forks
- 107
- Merge medio
- 2 d 22 h
- PR fusionados (30 d)
- 5
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de modelcontextprotocol/conformance
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
modelcontextprotocol/conformance#531 · 1 comentario ·
Los mantenedores suelen responder en 4 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
modelcontextprotocol/conformance#530 ·
Los mantenedores suelen responder en 4 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
modelcontextprotocol/conformance#519 ·
Los mantenedores suelen responder en 4 días
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
modelcontextprotocol/conformance#315 · 1 comentario ·
Los mantenedores suelen responder en 4 días
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
modelcontextprotocol/conformance#312 · 1 comentario ·
Los mantenedores suelen responder en 4 días
Todos los issues de modelcontextprotocol/conformance
Issues similares
-
refactor
Dificultad 2/5 Medio día Aptitud para principiantes 84/100
Los mantenedores suelen responder en 5 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
OHDSI/Data2Evidence#3450 ·
Los mantenedores suelen responder en 2 días
-
e2e-failure ready-to-code
Dificultad 2/5 1-3 horas Aptitud para principiantes 90/100
redhat-developer/rhdh-plugin-export-overlays#4011 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
automation missing-model model-sync provider:ofox
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
anomalyco/models.dev#8421 ·
Los mantenedores suelen responder en 1 día
-
SlackAdapter and TelegramAdapter are not assignable to Adapter under exactOptionalPropertyTypesAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 1 día