Skip to content

Improve DNS rebinding protection visibility and Host rejection diagnostics #3784

Open

Description

@alemaiorano

Correction and scope

The original description overstated the affected configurations. I withdraw the claim that every deployment omitting TransportSecuritySettings is vulnerable.

Read-only source inspection of current main at commit 77001c9 shows:

  • TransportSecuritySettings.enable_dns_rebinding_protection defaults to True.
  • TransportSecurityMiddleware(settings=None) explicitly falls back to protection disabled for backward compatibility.
  • The standard streamable_http_app() and sse_app() helpers default to host="127.0.0.1" and automatically enable protection when no explicit settings are supplied and the configured host is 127.0.0.1, localhost, or ::1.
  • Direct construction of lower-level HTTP transports without security settings bypasses that helper configuration, including on loopback. Configuring a helper with a non-loopback host without appropriate transport_security settings also leaves these SDK checks disabled. Explicitly disabling protection is another possible configuration.

These are potential exposure paths, not evidence that every such deployment is exploitable. Actual risk depends on browser reachability and other deployment controls. This report is based on source inspection and discussion; it does not include a reproduced attack or a verified vulnerable deployment.

Source: middleware and settings, Streamable HTTP helper, SSE helper.

Previous maintainer decision

#3562 was closed as not planned on October 6, 2026. The maintainer explained that enabling protection unconditionally at the low-level transport layer could reject requests in existing deployments. A bind address such as 0.0.0.0 also does not identify the public hostname needed for an allowlist.

This proposal respects that compatibility decision: retain existing defaults and validation behavior, while making the effective configuration and rejection causes easier to inspect.

Remaining visibility gap

The middleware currently does not log its effective security configuration at initialization. Operators therefore cannot readily distinguish helper-enabled protection, explicit settings, and the disabled fallback from startup logs.

Rejected Host headers produce 421 Invalid Host header; rejected Origin headers produce 403 Invalid Origin header. Existing warnings identify missing or invalid headers, but do not explain the relevant setting or how to correct a proxy/public-host configuration.

This can obscure deployments where protection is disabled and make legitimate Host rejections difficult to diagnose.

Proposed improvement

  1. Log the effective protection state and configured host/origin allowlists when the transport security configuration is initialized, covering both enabled and disabled states. Warn when protection is disabled and identify TransportSecuritySettings as the configuration entry point.
  2. Make Host rejection diagnostics actionable: identify Host validation as the cause, name TransportSecuritySettings.allowed_hosts, and include a safely escaped, bounded representation of the received Host value—or indicate that it was missing.
  3. Point operators toward explicitly configuring expected public/proxy hostnames and origins. Do not recommend disabling protection as the routine fix or automatically trust a rejected Host value.

Acceptance criteria

  • Initialization logging reports the effective enable_dns_rebinding_protection, allowed_hosts, and allowed_origins values after helper configuration has been applied. Disabled configurations produce a warning, including both omitted low-level settings and explicit opt-out.
  • Tests cover both helpers with each loopback host (127.0.0.1, localhost, ::1), a non-loopback helper configuration without settings, direct low-level construction without settings, and explicit enabled/disabled settings. Logged state matches the actual middleware configuration in each case.
  • Missing and disallowed Host headers still return HTTP 421. The response identifies allowed_hosts and the Host validation failure; operator logs include the safely represented received value or an explicit missing-header indicator.
  • Origin rejection remains distinguishable from Host rejection and retains HTTP 403. Allowed requests and disabled-protection behavior remain unchanged.
  • Diagnostics are tested through SSE connection establishment and message POSTs, plus Streamable HTTP requests. Tests include Host values with ports and bracketed IPv6, without changing allowlist matching semantics.
  • Header values in diagnostics are escaped and length-limited; responses do not expose the configured allowlists. Rejection guidance does not suggest accepting arbitrary hosts.
  • Documentation explains the protected helper defaults, lower-level and non-loopback configuration requirements, and a reverse-proxy example using explicit expected hosts/origins.

Related work and fix check

As of November 14, 2026, inspection of current main and related PRs did not identify a merged implementation of these visibility improvements:

Related discussion: #2688 and #1798. This issue focuses on effective-configuration visibility and actionable diagnostics, without reopening the unconditional default-on proposal or asserting a new confirmed vulnerability.

Activity

  1. added
    enhancementRequest for a new feature that's not currently supported
    on Oct 28, 2026
  2. sattyamjjain commented on Oct 29, 2026

    @sattyamjjain
  3. Ben-Home commented on Oct 29, 2026

    @Ben-Home
  4. sattyamjjain commented on Oct 31, 2026

    @sattyamjjain
  5. changed the title [-]Security: DNS rebinding protection is opt-in, not enabled by default[/-] [+]Improve DNS rebinding protection visibility and Host rejection diagnostics[/+] on Nov 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementRequest for a new feature that's not currently supported

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions