CVE-2025-58751: Vite Vite Middleware May Serve Files Vulnerability

LOW
Advisory Identifier: GHSA-g4jq-h2w9-997c
CWE-284 CWE-200 CWE-22
Published
Advisory Summary

CVE-2025-58751 is a LOW vite middleware may serve files vulnerability (CWE-284: Improper Access Control) affecting Vite libraries in the npm ecosystem. The issue involves vite middleware may serve files starting with the same name with the public directory. Remediation is available by upgrading affected packages to version 7.1.5, 7.0.7, 6.3.6, 5.4.20.

CVE-2025-58751 at a Glance

CVE Identifier CVE-2025-58751
GHSA Identifier GHSA-g4jq-h2w9-997c
Severity LOW
CVSS v3.1 Base Score N/A
CWE Classification CWE-284: Improper Access Control
Affected Product Vite
Package Ecosystem npm
Published Date
Last Updated

How to Fix CVE-2025-58751

To remediate this vulnerability, upgrade all affected Vite dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

vite fixed: 7.1.5
npm install vite@7.1.5
vite fixed: 7.0.7
npm install vite@7.0.7
vite fixed: 6.3.6
npm install vite@6.3.6
vite fixed: 5.4.20
npm install vite@5.4.20
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls vite

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2025-58751, inspect your project dependencies using npm:

npm ls vite

Analyze the terminal output to locate any version of Vite in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 7.1.5), your application is affected.

Note: The npm ls vite command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-284: Improper Access Control, where the product does not restrict or incorrectly restricts access to a resource from an unauthorized actor. In Vite, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary Files starting with the same name with the public directory were served bypassing the `server.fs` settings. ### Impact Only apps that match the following conditions are affected: - explicitly exposes the Vite dev server to the network (using --host or [`server.host` config option](https://vitejs.dev/config/server-options.html#server-host)) - uses [the public directory feature](https://vite.dev/guide/assets.html#the-public-directory) (enabled by default) - a symlink exists in the public directory ### Details The [servePublicMiddleware](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L79) function is in charge of serving public files from the server. It returns the [viteServePublicMiddleware](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L106) function which runs the needed tests and serves the page. The viteServePublicMiddleware function [checks if the publicFiles variable is defined](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L111), and then uses it to determine if the requested page is public. In the case that the publicFiles is undefined, the code will treat the requested page as a public page, and go on with the serving function. [publicFiles may be undefined if there is a symbolic link anywhere inside the public directory](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/publicDir.ts#L21). In that case, every requested page will be passed to the public serving function. The serving function is based on the [sirv](https://github.com/lukeed/sirv) library. Vite patches the library to add the possibility to test loading access to pages, but when the public page middleware [disables this functionality](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L89) since public pages are meant to be available always, regardless of whether they are in the allow or deny list. In the case of public pages, the serving function is [provided with the path to the public directory](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L85) as a root directory. The code of the sirv library [uses the join function to get the full path to the requested file](https://github.com/lukeed/sirv/blob/d061616827dd32d53b61ec9530c9445c8f592620/packages/sirv/index.mjs#L42). For example, if the public directory is "/www/public", and the requested file is "myfile", the code will join them to the string "/www/public/myfile". The code will then pass this string to the normalize function. Afterwards, the code will [use the string's startsWith function](https://github.com/lukeed/sirv/blob/d061616827dd32d53b61ec9530c9445c8f592620/packages/sirv/index.mjs#L43) to determine whether the created path is within the given directory or not. Only if it is, it will be served. Since [sirv trims the trailing slash of the public directory](https://github.com/lukeed/sirv/blob/d061616827dd32d53b61ec9530c9445c8f592620/packages/sirv/index.mjs#L119), the string's startsWith function may return true even if the created path is not within the public directory. For example, if the server's root is at "/www", and the public directory is at "/www/p", if the created path will be "/www/private.txt", the startsWith function will still return true, because the string "/www/private.txt" starts with  "/www/p". To achieve this, the attacker will use ".." to ask for the file "../private.txt". The code will then join it to the "/www/p" string, and will receive "/www/p/../private.txt". Then, the normalize function will return "/www/private.txt", which will then be passed to the startsWith function, which will return true, and the processing of the page will continue without checking the deny list (since this is the public directory middleware which doesn't check that). ### PoC Execute the following shell commands: ``` npm create vite@latest cd vite-project/ mkdir p cd p ln -s a b cd .. echo 'import path from "node:path"; import { defineConfig } from "vite"; export default defineConfig({publicDir: path.resolve(__dirname, "p/"), server: {fs: {deny: [path.resolve(__dirname, "private.txt")]}}})' > vite.config.js echo "secret" > private.txt npm install npm run dev ``` Then, in a different shell, run the following command: `curl -v --path-as-is 'http://localhost:5173/private.txt'` You will receive a 403 HTTP Response,  because private.txt is denied. Now in the same shell run the following command: `curl -v --path-as-is 'http://localhost:5173/../private.txt'` You will receive the contents of private.txt. ### Related links - https://github.com/lukeed/sirv/commit/f0113f3f8266328d804ee808f763a3c11f8997eb

CVE-2025-58751 Affected Vite Versions

4 component(s)
Fixed Versions:
7.1.57.0.76.3.65.4.20
Product / Package Ecosystem Affected Versions Fixed Version
vite
npm
≥ 7.1.0
< 7.1.5
7.1.5
vite
npm
≥ 7.0.0
< 7.0.7
7.0.7
vite
npm
≥ 6.0.0
< 6.3.6
6.3.6
vite
npm
< 5.4.20
5.4.20

References

Frequently Asked Questions

What is CVE-2025-58751?
CVE-2025-58751 is a security vulnerability in Vite involving Vite middleware may serve files starting with the same name with the public directory under CWE-284: Improper Access Control.
Which Vite versions are affected?
Affected versions include releases prior to 7.1.5, 7.0.7, 6.3.6, 5.4.20 across affected packages: vite.
What version fixes CVE-2025-58751?
Upgrading to 7.1.5, 7.0.7, 6.3.6, 5.4.20 (or the latest patched release for your respective branch) resolves the vulnerability.
Is vite affected?
Yes, vite is affected in releases prior to 7.1.5, 7.0.7, 6.3.6, 5.4.20. Upgrade your dependency to 7.1.5, 7.0.7, 6.3.6, 5.4.20 or later.
What CWE is associated with CVE-2025-58751?
CVE-2025-58751 is classified under CWE-284: Improper Access Control (The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.).
How can I check npm dependencies for CVE-2025-58751?
Run the dependency tree command: 'npm ls vite'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-g4jq-h2w9-997c",
  "modified" : "2025-09-09T20:55:56Z",
  "published" : "2025-09-09T20:55:56Z",
  "aliases" : [ "CVE-2025-58751" ],
  "summary" : "Vite middleware may serve files starting with the same name with the public directory",
  "details" : "### Summary\nFiles starting with the same name with the public directory were served bypassing the `server.fs` settings.\n\n### Impact\nOnly apps that match the following conditions are affected:\n\n- explicitly exposes the Vite dev server to the network (using --host or [`server.host` config option](https://vitejs.dev/config/server-options.html#server-host))\n- uses [the public directory feature](https://vite.dev/guide/assets.html#the-public-directory) (enabled by default)\n- a symlink exists in the public directory\n\n### Details\nThe [servePublicMiddleware](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L79) function is in charge of serving public files from the server. It returns the [viteServePublicMiddleware](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L106) function which runs the needed tests and serves the page. The viteServePublicMiddleware function [checks if the publicFiles variable is defined](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L111), and then uses it to determine if the requested page is public. In the case that the publicFiles is undefined, the code will treat the requested page as a public page, and go on with the serving function. [publicFiles may be undefined if there is a symbolic link anywhere inside the public directory](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/publicDir.ts#L21). In that case, every requested page will be passed to the public serving function. The serving function is based on the [sirv](https://github.com/lukeed/sirv) library. Vite patches the library to add the possibility to test loading access to pages, but when the public page middleware [disables this functionality](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L89) since public pages are meant to be available always, regardless of whether they are in the allow or deny list.\n\nIn the case of public pages, the serving function is [provided with the path to the public directory](https://github.com/vitejs/vite/blob/9719497adec4ad5ead21cafa19a324bb1d480194/packages/vite/src/node/server/middlewares/static.ts#L85) as a root directory. The code of the sirv library [uses the join function to get the full path to the requested file](https://github.com/lukeed/sirv/blob/d061616827dd32d53b61ec9530c9445c8f592620/packages/sirv/index.mjs#L42). For example, if the public directory is \"/www/public\", and the requested file is \"myfile\", the code will join them to the string \"/www/public/myfile\". The code will then pass this string to the normalize function. Afterwards, the code will [use the string's startsWith function](https://github.com/lukeed/sirv/blob/d061616827dd32d53b61ec9530c9445c8f592620/packages/sirv/index.mjs#L43) to determine whether the created path is within the given directory or not. Only if it is, it will be served.\n\nSince [sirv trims the trailing slash of the public directory](https://github.com/lukeed/sirv/blob/d061616827dd32d53b61ec9530c9445c8f592620/packages/sirv/index.mjs#L119), the string's startsWith function may return true even if the created path is not within the public directory. For example, if the server's root is at \"/www\", and the public directory is at \"/www/p\", if the created path will be \"/www/private.txt\", the startsWith function will still return true, because the string \"/www/private.txt\" starts with  \"/www/p\". To achieve this, the attacker will use \"..\" to ask for the file \"../private.txt\". The code will then join it to the \"/www/p\" string, and will receive \"/www/p/../private.txt\". Then, the normalize function will return \"/www/private.txt\", which will then be passed to the startsWith function, which will return true, and the processing of the page will continue without checking the deny list (since this is the public directory middleware which doesn't check that).\n\n### PoC\nExecute the following shell commands:\n\n```\nnpm  create  vite@latest\ncd vite-project/\nmkdir p\ncd p\nln -s a b\ncd ..\necho  'import path from \"node:path\"; import { defineConfig } from \"vite\"; export default defineConfig({publicDir: path.resolve(__dirname, \"p/\"), server: {fs: {deny: [path.resolve(__dirname, \"private.txt\")]}}})' > vite.config.js\necho  \"secret\" > private.txt\nnpm install\nnpm run dev\n```\n\nThen, in a different shell, run the following command:\n\n`curl -v --path-as-is 'http://localhost:5173/private.txt'`\n\nYou will receive a 403 HTTP Response,  because private.txt is denied.\n\nNow in the same shell run the following command:\n\n`curl -v --path-as-is 'http://localhost:5173/../private.txt'`\n\nYou will receive the contents of private.txt.\n\n### Related links\n- https://github.com/lukeed/sirv/commit/f0113f3f8266328d804ee808f763a3c11f8997eb",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "vite"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "7.1.0"
      }, {
        "fixed" : "7.1.5"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 7.1.4"
    }
  }, {
    "package" : {
      "ecosystem" : "npm",
      "name" : "vite"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "7.0.0"
      }, {
        "fixed" : "7.0.7"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 7.0.6"
    }
  }, {
    "package" : {
      "ecosystem" : "npm",
      "name" : "vite"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "6.0.0"
      }, {
        "fixed" : "6.3.6"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 6.3.5"
    }
  }, {
    "package" : {
      "ecosystem" : "npm",
      "name" : "vite"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "5.4.20"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 5.4.19"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/vitejs/vite/security/advisories/GHSA-g4jq-h2w9-997c"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2025-58751"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/lukeed/sirv/commit/f0113f3f8266328d804ee808f763a3c11f8997eb"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/vitejs/vite/commit/09f2b52e8d5907f26602653caf41b3a56692600d"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/vitejs/vite/commit/4f1c35bcbb5830290c694aa14b6789e07450f069"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/vitejs/vite/commit/63e2a5d232218f3f8d852056751e609a5367aaec"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/vitejs/vite/commit/e11d24008b97d4ca731ecc1a3b95260a6d12e7e0"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/vitejs/vite"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-200", "CWE-22", "CWE-284" ],
    "severity" : "LOW",
    "github_reviewed" : true,
    "github_reviewed_at" : "2025-09-09T20:55:56Z",
    "nvd_published_at" : "2025-09-08T23:15:36Z"
  }
}