Skip to content

[Security] Bump vite from 5.2.11 to 5.4.18

Dependabot requested to merge dependabot-npm_and_yarn-vite-5.4.18 into main

Bumps vite from 5.2.11 to 5.4.18. This update includes security fixes.

Vulnerabilities fixed

Vite's server.fs.deny is bypassed when using ?import&raw

Summary

The contents of arbitrary files can be returned to the browser.

Details

@fs denies access to files outside of Vite serving allow list. Adding ?import&raw to the URL bypasses this limitation and returns the file content if it exists.

PoC

$ npm create vite@latest
$ cd vite-project/
$ npm install
$ npm run dev
$ echo "top secret content" > /tmp/secret.txt
expected behaviour
$ curl "http://localhost:5173/@​fs/tmp/secret.txt"
<body>
  <h1>403 Restricted</h1>

</tr></table>

... (truncated)

Patched versions: 5.1.8; 5.2.14; 3.2.11; 4.5.4; 5.3.6; 5.4.6 Affected versions: >= 5.0.0, = 5.4.0, <= 5.4.5

Vite DOM Clobbering gadget found in vite bundled scripts that leads to XSS

Summary

We discovered a DOM Clobbering vulnerability in Vite when building scripts to cjs/iife/umd output format. The DOM Clobbering gadget in the module can lead to cross-site scripting (XSS) in web pages where scriptless attacker-controlled HTML elements (e.g., an img tag with an unsanitized name attribute) are present.

Note that, we have identified similar security issues in Webpack: https://github.com/webpack/webpack/security/advisories/GHSA-4vvj-4cpr-p986

Details

Backgrounds

DOM Clobbering is a type of code-reuse attack where the attacker first embeds a piece of non-script, seemingly benign HTML markups in the webpage (e.g. through a post or comment) and leverages the gadgets (pieces of js code) living in the existing javascript code to transform it into executable code. More for information about DOM Clobbering, here are some references:

[1] https://scnps.co/papers/sp23_domclob.pdf [2] https://research.securitum.com/xss-in-amp4email-dom-clobbering/

Gadgets found in Vite

We have identified a DOM Clobbering vulnerability in Vite bundled scripts, particularly when the scripts dynamically import other scripts from the assets folder and the developer sets the build output format to cjs, iife, or umd. In such cases, Vite replaces relative paths starting with __VITE_ASSET__ using the URL retrieved from document.currentScript.

However, this implementation is vulnerable to a DOM Clobbering attack. The document.currentScript lookup can be shadowed by an attacker via the browser's named DOM tree element access mechanism. This manipulation allows an attacker to replace the intended script element with a malicious HTML element. When this happens, the src attribute of the attacker-controlled element is used as the URL for importing scripts, potentially leading to the dynamic loading of scripts from an attacker-controlled server.

... (truncated)

Patched versions: 5.1.8; 3.2.11; 5.2.14; 5.3.6; 5.4.6; 4.5.4 Affected versions: >= 5.0.0, = 4.0.0, < 4.5.4

Websites were able to send any requests to the development server and read the response in vite

Summary

Vite allowed any websites to send any requests to the development server and read the response due to default CORS settings and lack of validation on the Origin header for WebSocket connections.

[!WARNING] This vulnerability even applies to users that only run the Vite dev server on the local machine and does not expose the dev server to the network.

Upgrade Path

Users that does not match either of the following conditions should be able to upgrade to a newer version of Vite that fixes the vulnerability without any additional configuration.

  • Using the backend integration feature
  • Using a reverse proxy in front of Vite
  • Accessing the development server via a domain other than localhost or *.localhost
  • Using a plugin / framework that connects to the WebSocket server on their own from the browser

Using the backend integration feature

If you are using the backend integration feature and not setting server.origin, you need to add the origin of the backend server to the server.cors.origin option. Make sure to set a specific origin rather than *, otherwise any origin can access your development server.

Using a reverse proxy in front of Vite

If you are using a reverse proxy in front of Vite and sending requests to Vite with a hostname other than localhost or *.localhost, you need to add the hostname to the new server.allowedHosts option. For example, if the reverse proxy is sending requests to http://vite:5173, you need to add vite to the server.allowedHosts option.

... (truncated)

Patched versions: 4.5.6; 5.4.12; 6.0.9 Affected versions: = 6.0.0, <= 6.0.8

Vite bypasses server.fs.deny when using ?raw??

Summary

The contents of arbitrary files can be returned to the browser.

Impact

Only apps explicitly exposing the Vite dev server to the network (using --host or server.host config option) are affected.

Details

@fs denies access to files outside of Vite serving allow list. Adding ?raw?? or ?import&raw?? to the URL bypasses this limitation and returns the file content if it exists. This bypass exists because trailing separators such as ? are removed in several places, but are not accounted for in query string regexes.

PoC

$ npm create vite@latest
$ cd vite-project/
$ npm install
$ npm run dev
$ echo "top secret content" > /tmp/secret.txt
expected behaviour
$ curl "http://localhost:5173/@​fs/tmp/secret.txt"
</tr></table>

... (truncated)

Patched versions: 4.5.10; 5.4.15; 6.0.12; 6.1.2; 6.2.3 Affected versions: = 6.2.0, < 6.2.3

Vite has a server.fs.deny bypassed for inline and raw with ?import query

Summary

The contents of arbitrary files can be returned to the browser.

Impact

Only apps explicitly exposing the Vite dev server to the network (using --host or server.host config option) are affected.

Details

  • base64 encoded content of non-allowed files is exposed using ?inline&import (originally reported as ?import&?inline=1.wasm?init)
  • content of non-allowed files is exposed using ?raw?import

/@fs/ isn't needed to reproduce the issue for files inside the project root.

PoC

Original report (check details above for simplified cases):

The ?import&?inline=1.wasm?init ending allows attackers to read arbitrary files and returns the file content if it exists. Base64 decoding needs to be performed twice

</tr></table> 

... (truncated)

Patched versions: 4.5.11; 5.4.16; 6.0.13; 6.1.3; 6.2.4 Affected versions: = 6.2.0, < 6.2.4

Vite allows server.fs.deny to be bypassed with .svg or relative paths

Summary

The contents of arbitrary files can be returned to the browser.

Impact

Only apps explicitly exposing the Vite dev server to the network (using --host or server.host config option) are affected..

Details

.svg

Requests ending with .svg are loaded at this line. https://github.com/vitejs/vite/blob/037f801075ec35bb6e52145d659f71a23813c48f/packages/vite/src/node/plugins/asset.ts#L285-L290 By adding ?.svg with ?.wasm?init or with sec-fetch-dest: script header, the restriction was able to bypass.

This bypass is only possible if the file is smaller than build.assetsInlineLimit (default: 4kB) and when using Vite 6.0+.

relative paths

... (truncated)

Patched versions: 4.5.12; 5.4.17; 6.0.14; 6.1.4; 6.2.5 Affected versions: = 6.2.0, < 6.2.5

Changelog

Sourced from vite's changelog.

5.4.18 (2025-04-10)

5.4.17 (2025-04-03)

5.4.16 (2025-03-31)

5.4.15 (2025-03-24)

5.4.14 (2025-01-21)

5.4.13 (2025-01-20)

5.4.12 (2025-01-20)

  • fix!: check host header to prevent DNS rebinding attacks and introduce server.allowedHosts (9da4abc)
  • fix!: default server.cors: false to disallow fetching from untrusted origins (dfea38f)
  • fix: verify token for HMR WebSocket connection (b71a5c8)
  • chore: add deps update changelog (ecd2375)

5.4.11 (2024-11-11)

  • fix(deps): update dependencies of postcss-modules (ceb15db), closes #18617

... (truncated)

Commits

Merge request reports

Loading