Skip to the page

Why dev servers block unknown hosts

Vite, Next.js, Django and Rails turn away addresses they don't know, to stop DNS rebinding. How the attack works, the CVEs behind it, and the safe fixes.

By Mads Sauer. Published .

Dev servers block unknown hosts to stop DNS rebinding, a trick that lets any website you visit read pages from the dev server running on your own computer. Vite, Next.js, webpack-dev-server, Django and Rails check the name each request was sent to, and answer only the names they expect.

That is why a tunnel, or a phone on your Wi-Fi, can run into a “Blocked request” or a page that won't load: the check can't tell a new address you trust from an attacker's.

What DNS rebinding is

  1. While your dev server runs, you open a page on a site an attacker controls, say attacker.example.
  2. Its DNS first answers with the attacker's server, then, moments later, with 127.0.0.1: your own computer.
  3. Script on the page asks the same name, on port 5173, for /src/main.ts. To the browser, that is the page's own site, so it lets the script read the answer.
  4. The request lands on your dev server, which hands over your source.

Browsers keep sites apart by name, not by address, and that is the gap. Vite's advisory puts it in one line:

“an attacker can send arbitrary requests to the development server bypassing the same-origin policy.”

GitHub advisory database, GHSA-vg6x-rcgg-rjx6 (CVE-2025-24010), Vite

The fix is cheap. The request still says it is for attacker.example:5173 in its Host header, a name the dev server never meant to answer, so it refuses.

Why dev servers are worth the trouble

  • They serve your source code, often with source maps.
  • They have no login, because only you are meant to reach them.
  • Some come with debug consoles that run code, as Flask's does.
  • They listen on localhost, which feels private, so nobody thinks to lock them.

Who checks what

What each dev server checks, and what it allows by default
Dev serverChecksAllows by default
ViteHost, against server.allowedHosts“localhost and domains under .localhost and all IP addresses are allowed by default.”
Next.jsThe Origin of requests for its dev resources, against allowedDevOrigins“The dev server already allows localhost, its subdomains, and the hostname it was started with.”
webpack-dev-serverHost, against allowedHostslocalhost, its own host and its WebSocket's host
DjangoHost, against ALLOWED_HOSTSWith DEBUG on and the list empty: ['.localhost', '127.0.0.1', '[::1]']
RailsHost and the last X-Forwarded-Host, against config.hostsIn development: any IPv4 or IPv6 address, and localhost

Django and Rails have checked hosts for years. Django's docs on ALLOWED_HOSTS: “This is a security measure to prevent HTTP Host header attacks, which are possible even under many seemingly-safe web server configurations.” Rails' guide, on its host authorization middleware: “Prevents against DNS rebinding and other Host header attacks.” It answers a name it doesn't allow with 403 Forbidden.

Vite: CVE-2025-24010

Vite added its check after an advisory published on 20 January 2025, fixed in versions 6.0.9, 5.4.12 and 4.5.6. Before it, any site could send requests to a Vite dev server and read the answers.

Next.js: CVE-2025-48068

Next.js published its advisory on 28 May 2025: “This issue may have allowed limited source code exposure when the dev server was running with the App Router enabled.” The fix in 15.2.2 only warned, unless you set allowedDevOrigins. Version 16.2.0, released on 18 March 2026, made blocking the default: a request from an origin it doesn't know gets a 403.

What each one says when it blocks

The messages dev servers give for a host they don't allow
Dev serverWhat it says
ViteBlocked request. This host ("calm-otter-4821.ouicu.app") is not allowed.
Next.jsBlocked cross-origin request to Next.js dev resource /_next/hmr from "calm-otter-4821.ouicu.app".
webpack-dev-serverInvalid Host header
DjangoInvalid HTTP_HOST header: '192.168.1.20:8000'. You may need to add '192.168.1.20' to ALLOWED_HOSTS.
RailsBlocked hosts: calm-otter-4821.ouicu.app

Next.js is the quiet one: it says so in the terminal, while the page itself loads and runs with only hot reload refused, so edits never show and it looks frozen rather than blocked.

The wrong fix: allow everything

Most of them can turn the check off, and their docs warn against it. Vite's:

“Setting server.allowedHosts to true allows any website to send requests to your dev server through DNS rebinding attacks, allowing them to download your source code and content.”

Vite docs, Server Options

webpack-dev-server says the same of allowedHosts: "all": “THIS IS NOT RECOMMENDED as apps that do not check the host are vulnerable to DNS rebinding attacks.” It works until the day you open the wrong page with the dev server running.

The right fixes

Allow the one name you use

Add the address a phone or a tunnel uses, and nothing else. With a tunnel address like calm-otter-4821.ouicu.app:

vite.config.ts
export default defineConfig({  server: { allowedHosts: ["calm-otter-4821.ouicu.app"] },});
next.config.ts
const nextConfig: NextConfig = {  allowedDevOrigins: ["calm-otter-4821.ouicu.app"],};
Django: settings.py, and Rails: config/environments/development.rb
ALLOWED_HOSTS = ["calm-otter-4821.ouicu.app"]config.hosts << "calm-otter-4821.ouicu.app"

The catch: a tunnel that draws a new name each time means a new line each time.

Each framework's guide has its exact setting, and what else it checks, tested through a link: Vite, Next.js, Django, Rails, Angular and Create React App.

Or let the tunnel say localhost

A tunnel can send each request on with Host set to the address your dev server expects. ngrok does it when asked: ngrok http --host-header=rewrite 80. ouicu does it on every request: your dev server sees Host: localhost:5173, and the public name arrives in X-Forwarded-Host. For hot reload and Next.js's dev requests, ouicu also changes the preview's own Origin to http://localhost:5173, so Vite, Next.js and webpack-dev-server need no change.

This keeps the protection where it matters. A rebinding attack reaches your dev server straight from your browser, with the attacker's name in Host, and is still refused. Only requests through the tunnel you started arrive as localhost.

Three limits remain:

  • Rails checks the last X-Forwarded-Host as well, so it still needs the public name in config.hosts (share a Rails dev server).
  • A form post keeps the public Origin. A framework that compares it with the host it sees may refuse posts until you add the public address to its trusted origins, as Django does (share a Django dev server).
  • A page told to open its hot reload socket on the dev server's own port can't, as a link has no such port: Create React App until WDS_SOCKET_PORT=0 (share a React app).

Questions

Is it safe to set allowedHosts to true?

No. It turns off the one check that stops other websites from reading your dev server, as Vite's own warning above says. List the names you use instead.

Why is my phone blocked when localhost works?

The phone uses your computer's network address. Vite and Rails allow addresses like that by default; Next.js and Django don't. The fixes are in localhost refused to connect on your phone.

Does Vite check hosts over https?

Not when Vite serves https itself. Its docs, under server.allowedHosts: “When using HTTPS, this check is skipped.”

Share without changing a setting

Give the dev server a link, with its checks left on:

ouicu share 5173

On Free, a share runs for up to 2 hours, and visitors see a short notice from ouicu first. How the link reaches your computer is in what a localhost tunnel is.

Sources

Prices, defaults and quotes about other products, and the day each was last checked at its source.

  1. GHSA-vg6x-rcgg-rjx6 (CVE-2025-24010), Vite, GitHub advisory database. Checked .
  2. GHSA-3h52-269p-cp9r (CVE-2025-48068), Next.js, GitHub advisory database. Checked .
  3. next: versions, npm. Checked .
  4. Server Options, Vite docs. Checked .
  5. allowedDevOrigins, Next.js docs. Checked .
  6. Settings, Django docs. Checked .
  7. Configuring Rails Applications, Rails Guides. Checked .
  8. hostCheck.ts, Vite on GitHub. Checked .
  9. block-cross-site-dev.ts, Next.js on GitHub. Checked .
  10. lib/Server.js, webpack-dev-server on GitHub. Checked .
  11. django/http/request.py, Django on GitHub. Checked .
  12. host_authorization.rb, Rails on GitHub. Checked .
  13. DevServer, webpack docs. Checked .
  14. Virtual hosts, ngrok docs. Checked .