Cloudanix VulnDB

CVE-2025-32395

None

CVSS

—

EPSS

1.8%

Published

Apr 10, 2025

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A publicly reachable development server could let outsiders download private project files and secrets from the machine running it.

Weaponized
Exploitation
Remote Unauthenticated
Attacker needs
None
Complexity
Moderate
Impact
Data Exposure
Component
Web Framework
Class
Path Traversal
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

This is a path traversal / arbitrary file read vulnerability in the Vite development server when it is explicitly exposed to the network with --host or server.host and is running on Node.js or Bun. Vite relied on the assumption that req.url would not contain a literal # character because URL fragments are not valid in HTTP request-targets, but Node and Bun can pass such malformed requests to application code instead of rejecting them. By placing # in a crafted request path, an attacker can bypass Vite's server.fs.deny checks and cause the dev server to return files that should have been blocked, potentially including source code, configuration files, environment files, credentials, SSH keys, tokens, or other local files readable by the dev-server process. Integrity and availability are not directly impacted; the primary impact is high-confidence confidentiality loss.

Why it matters to the business

If an affected Vite dev server is reachable from an untrusted network, an unauthenticated attacker may be able to download sensitive local files from the developer workstation, build container, CI environment, or preview host running that server. The most serious outcomes are exposure of application secrets, cloud credentials, source code, internal API endpoints, dependency manifests, and private keys, which can enable follow-on compromise even though the flaw itself is limited to file disclosure. The issue is not in CISA KEV and has a relatively low EPSS score, but exploit maturity is listed as weaponized and the vulnerability has been public for 487 days, so internet-exposed development servers should be treated as urgent to find and remove.

How an attack unfolds

An attacker first identifies a Vite development server exposed on a network interface rather than bound only to localhost. They then send raw HTTP requests directly to the dev server, or through a permissive intermediary, using malformed request-targets that include a literal # character. Because Node.js and Bun may pass these invalid request paths to userland, Vite processes the request instead of the runtime rejecting it. The crafted path interferes with Vite's file-deny validation and allows the attacker to request files through Vite's file-serving behavior that should otherwise be blocked by server.fs.deny. The attacker iterates over common sensitive paths such as environment files, package metadata, source files, home-directory secrets, and operating-system files, then uses any disclosed credentials or application secrets for additional access outside the Vite server.

How to fix it

Upgrade Vite to a fixed release: 6.2.6 or later for the 6.2 line, 6.1.5 or later for the 6.1 line, 6.0.15 or later for the 6.0 line, 5.4.18 or later for the 5.4 line, or 4.5.13 or later for the 4.5 line. The upstream Git fix is commit d3dbf25fd5e21448f9ea6cec8fb5ac45d220037b. Remove duplicate or transitive vulnerable Vite versions from lockfiles and rebuild affected development containers or images. Do not expose Vite dev servers directly to the internet or untrusted networks; bind them to localhost by default and avoid --host 0.0.0.0 unless protected by a trusted network boundary. If remote access is required, place the service behind VPN, SSH tunneling, authenticated reverse proxy, firewall allowlists, or equivalent access controls, and configure edge proxies to reject request-targets containing literal # characters or other invalid HTTP syntax. Treat development servers as non-production tooling and avoid storing long-lived secrets in directories readable by the dev process.

How to confirm the fix worked

Confirm the installed Vite version in package manifests and lockfiles is at or above the fixed version for the relevant major/minor line. Use commands such as npm ls vite, pnpm why vite, yarn why vite, or bun pm ls to identify direct and transitive Vite installations. Verify that running dev servers are not bound to public or broad interfaces by checking process arguments, Vite config, container port mappings, and network listeners for --host, server.host, 0.0.0.0, ::, or externally published ports. From an untrusted network vantage point, confirm the Vite dev-server port is not reachable. Where safe and authorized, test that malformed HTTP requests containing a literal # in the request-target are rejected with an error by the fronting proxy or no longer disclose denied files after upgrading. Review deployed development images and CI preview environments to ensure they have been rebuilt with the fixed dependency rather than only updating source manifests.

Typical attack path

  1. Scan for reachable Vite development servers, commonly on ports such as 5173 or other configured dev-server ports.
  2. Confirm the service behaves like a Vite dev server by requesting known Vite paths or observing Vite-specific responses, headers, WebSocket endpoints, or error pages.
  3. Send a raw HTTP/1.1 or HTTP/2 request containing a literal # character in the request-target so the malformed URL reaches Vite on Node.js or Bun.
  4. Use the malformed path to bypass server.fs.deny checks and request local files through Vite's file-serving routes.
  5. Attempt to retrieve high-value files such as .env files, source files, package manifests, SSH keys, cloud credential files, or OS account files readable by the Vite process.
  6. Use any exposed secrets, tokens, or source-code intelligence to pivot to repositories, cloud services, APIs, CI/CD systems, or internal applications.

How to detect it

Review access logs from Vite, reverse proxies, load balancers, service meshes, developer tunnels, container ingress, and endpoint network sensors for malformed HTTP requests containing a literal # in the request path, especially combined with Vite file-serving routes such as /@fs/ or requests for sensitive filenames. Because some proxies normalize or drop fragments, prioritize raw request logs from the component closest to the Vite process when available. Look for repeated probing of common local paths, including .env, package.json, package-lock.json, pnpm-lock.yaml, yarn.lock, /etc/passwd, SSH key paths, cloud credential files, and source-code directories. On hosts running Vite, review shell history, process telemetry, and container runtime metadata for dev servers launched with --host, --host 0.0.0.0, server.host, or broad listener bindings. Investigate outbound authentication activity following any suspicious file-read attempts, such as new cloud API calls, repository access, or CI/CD token use. If suspicious requests targeted secrets, assume disclosed files may have been read even if the response body was not logged, and rotate affected credentials.

  • GET /@fs/
  • #
  • GET /@fs/#
  • GET /@fs/%23
  • /etc/passwd
  • .env
  • /.env
  • ../.env
  • id_rsa
  • /.ssh/id_rsa
  • /.aws/credentials
  • package.json
  • package-lock.json
  • pnpm-lock.yaml
  • yarn.lock
  • vite --host
  • --host 0.0.0.0
  • server.host
  • VITE v
  • /__vite_ping
  • /@@vite/client
  • /@vite/client

What your security team should do

  • Inventory all externally reachable Vite dev servers and prioritize any instance using --host, server.host, 0.0.0.0, or published container ports.
  • Upgrade Vite immediately to 6.2.6, 6.1.5, 6.0.15, 5.4.18, 4.5.13, or a later fixed release appropriate to the branch in use.
  • Block direct internet access to Vite dev servers; require VPN, SSH tunnel, authenticated reverse proxy, or firewall allowlisting for any remote development access.
  • Search source repositories, container images, and lockfiles for vulnerable Vite versions, including transitive copies pulled in by frameworks or tooling.
  • Add reverse-proxy or WAF rules that reject malformed request-targets containing literal # characters before they reach application runtimes.
  • Rotate secrets if logs show suspicious file-read attempts against .env files, credential paths, private keys, source files, or other sensitive local files.
  • Monitor for Vite-specific requests containing #, /@fs/, path traversal sequences, or common sensitive filenames, especially on ports commonly used for development servers.
  • Educate engineering teams that Vite dev server exposure is unsafe for untrusted networks and should not be used as a production or public preview server without additional controls.

The record

Vite is a frontend tooling framework for javascript. Prior to 6.2.6, 6.1.5, 6.0.15, 5.4.18, and 4.5.13, the contents of arbitrary files can be returned to the browser if the dev server is running on Node or Bun. HTTP 1.1 spec (RFC 9112) does not allow # in request-target. Although an attacker can send such a request. For those requests with an invalid request-line (it includes request-target), the spec recommends to reject them with 400 or 301. The same can be said for HTTP 2. On Node and Bun, those requests are not rejected internally and is passed to the user land. For those requests, the value of http.IncomingMessage.url contains #. Vite assumed req.url won't contain # when checking server.fs.deny, allowing those kinds of requests to bypass the check. Only apps explicitly exposing the Vite dev server to the network (using --host or server.host config option) and running the Vite dev server on runtimes that are not Deno (e.g. Node, Bun) are affected. This vulnerability is fixed in 6.2.6, 6.1.5, 6.0.15, 5.4.18, and 4.5.13.

Affected packages

Ecosystem Package Introduced Fixed
npm vite 0 4.5.13
npm vite 5.0.0 5.4.18
npm vite 6.0.0 6.0.15
npm vite 6.1.0 6.1.5
npm vite 6.2.0 6.2.6
Chainguard vitess-18.0 0 18.0.8-r12
Chainguard vitess-18.0-binaries 0 18.0.8-r12
Chainguard vitess-19.0 0 19.0.10-r7
Chainguard vitess-19.0-binaries 0 19.0.10-r7
Chainguard vitess-20.0 0 20.0.7-r1
Chainguard vitess-20.0-binaries 0 20.0.7-r1
Chainguard vitess-20.0-compat 0 20.0.7-r1
Chainguard vitess-21.0 0 21.0.4-r1
Chainguard vitess-21.0-binaries 0 21.0.4-r1
Chainguard vitess-21.0-compat 0 21.0.4-r1
Wolfi vitess-20.0 0 20.0.7-r1
Wolfi vitess-20.0-binaries 0 20.0.7-r1
Wolfi vitess-20.0-compat 0 20.0.7-r1
Wolfi vitess-21.0 0 21.0.4-r1
Wolfi vitess-21.0-binaries 0 21.0.4-r1
Wolfi vitess-21.0-compat 0 21.0.4-r1

Related vulnerabilities