← back
CVE-2025-31125mediumunder attackCWE-200CWE-284

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

90Vexday Risk Score

Patch now. It under exploitation confirmed by CISA and has a working public exploit.

ssvc Actcvss 5.3epss 59%
from disclosure to weapon1 days
Published on NVDMar 31
1st PoC+1d
CISA KEV+297d
exploitation probability
59%top 1% of all CVEs
observed exploitation
yesCISA + VulnCheck
9 public exploit(s)
Action required by CISAfederal deadline: 2026-02-12

Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.

Summary

O dev server do Vite (a partir de certas versões 4.x a 6.x) expõe o conteúdo de arquivos arbitrários do sistema de arquivos mesmo quando esses caminhos estão explicitamente bloqueados por server.fs.deny, através de combinações de query string envolvendo os parâmetros internos ?inline e ?raw junto com ?import. A falha só importa em ambientes onde o dev server foi deliberadamente exposto na rede via --host ou server.host — no padrão (bind em localhost) o risco prático é bem menor. Está no catálogo KEV da CISA, com exploração confirmada, o que eleva sua prioridade mesmo com CVSS moderado (5.3).

Technical detail

O Vite dev server aplica controle de acesso a arquivos via server.fs.allow (diretórios liberados) e server.fs.deny (padrões bloqueados, como .env e chaves) dentro do middleware de transformação de módulos (transform.ts). Essa checagem é feita pela função ensureServingAccess, mas antes do patch ela só era invocada quando a query string da requisição continha os parâmetros ?raw ou ?url — usados pelos plugins internos do Vite para servir o conteúdo bruto de um arquivo ou sua URL pública em vez de transformá-lo como módulo JS.

O parâmetro ?inline, usado por outros plugins internos (por exemplo, inlining de assets/WASM em base64), não estava incluído nessa checagem. Um atacante podia requisitar um caminho absoluto via /@fs/?import&inline (o relatório original usava a forma ?import&?inline=1.wasm?init, que aciona o pipeline de inicialização WASM) e receber o conteúdo do arquivo, codificado em base64 — no caso do vetor WASM, era necessário decodificar base64 duas vezes — sem que ensureServingAccess fosse chamada em nenhum momento. O advisory também lista um segundo padrão, ?raw?import (com '?' duplicado em vez do '&' esperado entre parâmetros), que contornava a checagem mesmo com o rawRE original já existente; o mecanismo exato dessa diferença de parsing de query não é detalhado nas fontes oficiais.

As regras de acesso não exigem que o caminho esteja fora do project root: o advisory afirma explicitamente que /@fs/ não é necessário para reproduzir o problema em arquivos dentro da raiz do projeto — ou seja, arquivos sensíveis dentro do próprio projeto, mas listados em fs.deny (como .env), também eram expostos.

O fix (commit 5967313) adiciona uma terceira regex, inlineRE (/[?&]inline\b/), à condição que dispara ensureServingAccess, de modo que qualquer requisição ao middleware de transformação contendo ?raw, ?url ou ?inline passe pela checagem de fs.allow/fs.deny antes de qualquer conteúdo ser retornado. CWE-200 (exposição de informação sensível) e CWE-284 (controle de acesso impróprio).

How it’s exploited

O pré-requisito determinante é a exposição do dev server na rede: por padrão o Vite escuta apenas em localhost, e só fica acessível remotamente quando o desenvolvedor usa a flag --host ou define server.host no config — cenário comum em ambientes de laboratório, VMs compartilhadas, containers com bind 0.0.0.0, ou desenvolvedores que expõem a porta 5173 por conveniência. Sem essa exposição a superfície de ataque prática é mínima.

Com o dev server acessível, a exploração é uma requisição HTTP GET simples contra uma URL como /@fs/?import&inline (ou variantes com ?raw?import), sem necessidade de autenticação (PR:N). O AC:H do CVSS reflete que o atacante precisa conhecer a estrutura de query específica que engana o middleware e, no caso do vetor original, decodificar base64 em duas camadas. O UI:R sugere que o padrão de exploração observado envolve a vítima com acesso à rede do dev server sendo induzida a acessar/carregar algo (ex.: um link ou página que dispara a requisição), e não necessariamente um ataque completamente sem interação.

O resultado final é leitura de arquivos arbitrários do sistema de arquivos do host onde o dev server roda — incluindo segredos, chaves privadas, arquivos .env e qualquer conteúdo acessível ao processo Node que executa o Vite. Não há impacto em integridade ou disponibilidade (I:N, A:N no vetor CVSS), é puramente divulgação de informação. A presença no catálogo KEV da CISA confirma exploração ativa observada, e existe template Nuclei público e PoC divulgada, o que reduz a barreira técnica para varreduras automatizadas contra instâncias expostas.

Versions

Affected
>=6.2.0 e =6.1.0 e =6.0.0 e =5.0.0 e <=5.4.15; <=4.5.10
Fixed in
>=6.2.4; >=6.1.3 e =6.0.13 e =5.4.16 e =4.5.11 e <5.0.0

How to protect

Atualizar para a versão corrigida da respectiva linha: 6.2.4 ou superior, 6.1.3 (branch 6.1.x), 6.0.13 (branch 6.0.x), 5.4.16 (branch 5.x) ou 4.5.11 (branch 4.x). Não há necessidade de mudar de major version — cada ramo tem seu backport.

Se a atualização não for viável de imediato, o paliativo real é parar de expor o dev server na rede: remover a flag --host e a opção server.host da configuração, restringindo o acesso a localhost. Isso neutraliza o vetor por completo, já que a falha só é explorável quando o servidor está acessível remotamente. Reforçar ou revisar server.fs.deny não é mitigação eficaz aqui — é exatamente esse mecanismo que a falha contorna, então confiar apenas nele sem atualizar deixa o ambiente vulnerável.

Dev server do Vite nunca deve ser tratado como serviço de produção ou exposto sem controle de rede (firewall, VPN, allowlist de IP) — isso vale independentemente desta CVE específica, dado o histórico recorrente de bypass de fs.deny/fs.allow nessa ferramenta.

How to detect

Em logs de acesso ao dev server (ou proxy na frente dele), procurar requisições cujo path inclua /@fs/ apontando para caminhos absolutos fora do diretório do projeto (ex.: /etc/passwd, chaves em /home, C:/windows/win.ini) combinados com query strings contendo inline junto com import, ou o padrão malformado raw?import (com '?' duplicado em vez de '&'). O padrão originalmente reportado, ?import&?inline=1.wasm?init, é um indicador de alta confiança de tentativa de exploração ou de uso do exploit público/template Nuclei conhecido.

Não há um único IOC de rede confiável além desses padrões de query, e como o Vite dev server normalmente não fica atrás de logging centralizado em ambientes de desenvolvimento, a ausência de log não indica ausência de tentativa — a visibilidade depende inteiramente de o operador ter exposto o processo Node com registro de acesso habilitado.

Researched and written with AI from the vendor advisory and public analysis, with the sources above. Always confirm the fixed version in the official advisory before acting.
Vite is a frontend tooling framework for javascript. Vite exposes content of non-allowed files using ?inline&import or ?raw?import. Only apps explicitly exposing the Vite dev server to the network (using --host or server.host config option) are affected. This vulnerability is fixed in 6.2.4, 6.1.3, 6.0.13, 5.4.16, and 4.5.11.
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N
Affected products
vitejs · vite
⚠ Public resources, to assess the exposure of systems you control or are authorized to test. Test only with authorization.