Implements switchVersionRequirement#302
Conversation
| fn load_switch_version_requirement() -> Result<Option<Range>, Error> { | ||
| let home_dir | ||
| = Path::home_dir()? | ||
| .ok_or(Error::MissingHomeFolder)?; |
There was a problem hiding this comment.
Missing home directory causes unnecessary validation failure
Medium Severity
When no home directory exists (common in Docker containers, some CI environments), load_switch_version_requirement returns Error::MissingHomeFolder instead of Ok(None). Since switchVersionRequirement can only be set in the home folder, the absence of a home folder inherently means no restriction is configured — it's logically equivalent to "file not found" and the function could safely return Ok(None). Instead, it breaks all yarn commands in these environments.
Reviewed by Cursor Bugbot for commit d79eeee. Configure here.
⏱️ Benchmark Resultsgatsby install-full-cold
📊 Raw benchmark data (gatsby install-full-cold)Base times: 4.307s, 4.353s, 4.293s, 4.316s, 4.309s, 4.239s, 4.324s, 4.237s, 4.199s, 4.314s, 4.281s, 4.270s, 4.322s, 4.308s, 4.154s, 4.239s, 4.250s, 4.367s, 4.374s, 4.190s, 4.313s, 4.343s, 4.294s, 4.308s, 4.246s, 4.307s, 4.356s, 4.304s, 4.325s, 4.286s Head times: 4.904s, 4.915s, 4.305s, 4.338s, 4.296s, 4.189s, 4.267s, 4.174s, 4.306s, 4.313s, 4.359s, 4.347s, 4.346s, 4.329s, 4.322s, 4.351s, 4.349s, 4.322s, 4.324s, 4.327s, 4.372s, 4.335s, 4.300s, 4.313s, 4.338s, 4.327s, 4.356s, 4.316s, 4.305s, 4.298s gatsby install-cache-only
📊 Raw benchmark data (gatsby install-cache-only)Base times: 1.264s, 1.265s, 1.262s, 1.250s, 1.260s, 1.253s, 1.258s, 1.264s, 1.259s, 1.266s, 1.271s, 1.259s, 1.267s, 1.250s, 1.245s, 1.275s, 1.271s, 1.254s, 1.246s, 1.243s, 1.287s, 1.273s, 1.249s, 1.275s, 1.254s, 1.275s, 1.262s, 1.281s, 1.265s, 1.265s Head times: 1.253s, 1.263s, 1.277s, 1.264s, 1.265s, 1.275s, 1.280s, 1.278s, 1.288s, 1.290s, 1.273s, 1.282s, 1.270s, 1.277s, 1.280s, 1.278s, 1.278s, 1.270s, 1.260s, 1.268s, 1.268s, 1.260s, 1.246s, 1.267s, 1.272s, 1.270s, 1.264s, 1.274s, 1.297s, 1.258s gatsby install-cache-and-lock (warm, with lockfile)
📊 Raw benchmark data (gatsby install-cache-and-lock (warm, with lockfile))Base times: 0.341s, 0.335s, 0.336s, 0.345s, 0.340s, 0.342s, 0.334s, 0.340s, 0.337s, 0.332s, 0.339s, 0.342s, 0.333s, 0.335s, 0.332s, 0.337s, 0.345s, 0.333s, 0.333s, 0.331s, 0.328s, 0.333s, 0.332s, 0.336s, 0.340s, 0.337s, 0.337s, 0.339s, 0.334s, 0.332s Head times: 0.340s, 0.339s, 0.340s, 0.338s, 0.342s, 0.339s, 0.341s, 0.338s, 0.346s, 0.341s, 0.342s, 0.347s, 0.338s, 0.342s, 0.341s, 0.338s, 0.336s, 0.336s, 0.334s, 0.335s, 0.337s, 0.336s, 0.335s, 0.342s, 0.339s, 0.338s, 0.342s, 0.338s, 0.338s, 0.334s |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Empty YAML file causes parsing error instead of succeeding
- Added an early return for empty config file contents so no YAML parse is attempted.
Or push these changes by commenting:
@cursor push 27d2e1622a
Preview (27d2e1622a)
diff --git a/packages/zpm-switch/src/config.rs b/packages/zpm-switch/src/config.rs
--- a/packages/zpm-switch/src/config.rs
+++ b/packages/zpm-switch/src/config.rs
@@ -31,6 +31,10 @@
return Ok(None);
};
+ if text.is_empty() {
+ return Ok(None);
+ }
+
let partial: PartialRcSettings
= serde_yaml::from_str(&text)?;You can send follow-ups to the cloud agent here.
Applied via @cursor push command
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Version validation bypassed via daemon command path
- Daemon startup now validates version references against switchVersionRequirement before installing or spawning Yarn, with an integration test covering the blocked daemon path.
Or push these changes by commenting:
@cursor push 0da0de1fe8
Preview (0da0de1fe8)
diff --git a/packages/zpm-switch/src/commands/switch/daemon_open.rs b/packages/zpm-switch/src/commands/switch/daemon_open.rs
--- a/packages/zpm-switch/src/commands/switch/daemon_open.rs
+++ b/packages/zpm-switch/src/commands/switch/daemon_open.rs
@@ -5,6 +5,7 @@
use zpm_utils::{Path, ToFileString};
use crate::{
+ config::validate_yarn_version,
cwd::get_final_cwd,
daemons::{self, DaemonEntry},
errors::Error,
@@ -77,6 +78,8 @@
match &reference {
PackageManagerReference::Version(version_ref) => {
+ validate_yarn_version(&version_ref.version)?;
+
let mut binary
= install_package_manager(version_ref).await?;
diff --git a/tests/acceptance-tests/pkg-tests-specs/sources/features/yarnSwitch.test.ts b/tests/acceptance-tests/pkg-tests-specs/sources/features/yarnSwitch.test.ts
--- a/tests/acceptance-tests/pkg-tests-specs/sources/features/yarnSwitch.test.ts
+++ b/tests/acceptance-tests/pkg-tests-specs/sources/features/yarnSwitch.test.ts
@@ -63,6 +63,24 @@
});
}),
);
+
+ test(
+ `it should fail to start a daemon when the version does not match the requirement`,
+ makeTemporaryEnv({
+ packageManager: `yarn@6.0.0`,
+ }, async ({path, runSwitch}) => {
+ const homePath = ppath.dirname(path);
+
+ await xfs.writeJsonPromise(ppath.join(homePath, Filename.rc), {
+ switchVersionRequirement: `>=99.0.0`,
+ });
+
+ await expect(runSwitch(`switch`, `daemon`, `--start`)).rejects.toMatchObject({
+ code: 1,
+ stdout: expect.stringContaining(`does not satisfy the required range`),
+ });
+ }),
+ );
});
});
});You can send follow-ups to the cloud agent here.
Applied via @cursor push command
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Version validation missing in tab completion execution path
- The proxy completion path now validates version references before installing or executing Yarn for completions.
Or push these changes by commenting:
@cursor push 436412ea93
Preview (436412ea93)
diff --git a/packages/zpm-switch/src/commands/proxy.rs b/packages/zpm-switch/src/commands/proxy.rs
--- a/packages/zpm-switch/src/commands/proxy.rs
+++ b/packages/zpm-switch/src/commands/proxy.rs
@@ -4,7 +4,7 @@
use clipanion::core::{Completion, CompletionContext};
use zpm_utils::{DataType, Note, ToFileString};
-use crate::{cwd::{get_fake_cwd, get_final_cwd}, errors::Error, install::install_package_manager, ipc::YARNSW_PATH_ENV, links::{LinkTarget, get_link, unset_link}, manifest::{LocalPackageManagerReference, PackageManagerField, PackageManagerReference, find_closest_package_manager}, yarn::get_default_yarn_version, yarn_enums::ReleaseLine};
+use crate::{config::validate_yarn_version, cwd::{get_fake_cwd, get_final_cwd}, errors::Error, install::install_package_manager, ipc::YARNSW_PATH_ENV, links::{LinkTarget, get_link, unset_link}, manifest::{LocalPackageManagerReference, PackageManagerField, PackageManagerReference, find_closest_package_manager}, yarn::get_default_yarn_version, yarn_enums::ReleaseLine};
use super::switch::explicit::ExplicitCommand;
@@ -74,6 +74,10 @@
let mut binary = match &reference {
PackageManagerReference::Version(params) => {
+ let Ok(()) = validate_yarn_version(¶ms.version) else {
+ return vec![];
+ };
+
let Ok(cmd) = install_package_manager(params).await else {
return vec![];
};You can send follow-ups to the cloud agent here.
Reviewed by Cursor Bugbot for commit dd6fa44. Configure here.
Applied via @cursor push command



This PR makes it possible to restrict the versions that Yarn Switch will allow to run based on the home folder configuration. Note that unlike other settings
switchVersionRequirementcan only be set in the home folder, since its purpose is to enhance security by disablingpackageManagerversions the user doesn't want to run.Note
Medium Risk
Adds a new pre-execution version gate for Yarn Switch based on parsing the user’s home
.yarnrc.yml, which can block command execution/daemon startup if misconfigured or if YAML parsing fails.Overview
Adds support for a new
switchVersionRequirementsetting (schema + merge support) to constrain which Yarn versions Yarn Switch will run.zpm-switchnow readsswitchVersionRequirementfrom the home.yarnrc.yml(viaserde_yaml) and validates resolved Yarn versions before running commands, generating completions, or starting a daemon; failures produce a newSwitchVersionMismatcherror. Acceptance tests cover success paths (missing/empty config, matching range) and failure paths (mismatching range, daemon start).Reviewed by Cursor Bugbot for commit 54cf9ae. Bugbot is set up for automated code reviews on this repo. Configure here.