Implements the concept of trusted project#303
Conversation
⏱️ Benchmark Resultsgatsby install-full-cold
📊 Raw benchmark data (gatsby install-full-cold)Base times: 4.377s, 4.429s, 4.483s, 4.387s, 4.345s, 4.384s, 4.441s, 4.330s, 4.365s, 4.299s, 4.350s, 4.330s, 4.403s, 4.341s, 4.429s, 4.310s, 4.385s, 4.417s, 4.371s, 4.332s, 4.438s, 4.413s, 4.386s, 4.406s, 4.368s, 4.401s, 4.355s, 4.422s, 4.422s, 4.356s Head times: 4.410s, 4.385s, 4.281s, 4.336s, 4.295s, 4.294s, 4.354s, 4.324s, 4.399s, 4.355s, 4.212s, 4.146s, 4.338s, 4.276s, 4.331s, 4.164s, 4.295s, 4.319s, 4.328s, 4.319s, 4.331s, 4.333s, 4.355s, 4.337s, 4.342s, 4.260s, 4.312s, 4.353s, 4.318s, 4.362s gatsby install-cache-only
📊 Raw benchmark data (gatsby install-cache-only)Base times: 1.285s, 1.260s, 1.259s, 1.270s, 1.284s, 1.265s, 1.281s, 1.277s, 1.279s, 1.245s, 1.295s, 1.268s, 1.276s, 1.278s, 1.300s, 1.260s, 1.308s, 1.292s, 1.263s, 1.283s, 1.275s, 1.283s, 1.269s, 1.271s, 1.261s, 1.266s, 1.265s, 1.272s, 1.254s, 1.261s Head times: 1.280s, 1.265s, 1.267s, 1.275s, 1.265s, 1.264s, 1.274s, 1.283s, 1.265s, 1.251s, 1.263s, 1.275s, 1.252s, 1.307s, 1.288s, 1.284s, 1.262s, 1.277s, 1.261s, 1.257s, 1.251s, 1.277s, 1.260s, 1.292s, 1.257s, 1.261s, 1.296s, 1.277s, 1.282s, 1.280s gatsby install-cache-and-lock (warm, with lockfile)
📊 Raw benchmark data (gatsby install-cache-and-lock (warm, with lockfile))Base times: 0.343s, 0.338s, 0.342s, 0.346s, 0.343s, 0.347s, 0.341s, 0.340s, 0.343s, 0.344s, 0.336s, 0.341s, 0.347s, 0.340s, 0.343s, 0.346s, 0.342s, 0.347s, 0.345s, 0.345s, 0.343s, 0.343s, 0.343s, 0.345s, 0.342s, 0.344s, 0.343s, 0.348s, 0.345s, 0.346s Head times: 0.343s, 0.344s, 0.343s, 0.338s, 0.340s, 0.343s, 0.342s, 0.347s, 0.343s, 0.346s, 0.344s, 0.344s, 0.343s, 0.353s, 0.341s, 0.361s, 0.372s, 0.344s, 0.338s, 0.336s, 0.336s, 0.336s, 0.339s, 0.344s, 0.339s, 0.367s, 0.340s, 0.342s, 0.339s, 0.342s |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Redundant subprocess spawning while holding the lock
- Moved project trust persistence into the prompt-only branch so cached trust results do not spawn redundant subprocesses while holding the mutex.
Or push these changes by commenting:
@cursor push 28c8352090
Preview (28c8352090)
diff --git a/packages/zpm/src/script.rs b/packages/zpm/src/script.rs
--- a/packages/zpm/src/script.rs
+++ b/packages/zpm/src/script.rs
@@ -653,14 +653,14 @@
let trusted
= Self::prompt_project_trust(project_cwd).await?;
+ Self::set_project_trust(&switch_path, project_cwd, trusted).await?;
+
*prompt_result = Some(trusted);
trusted
},
};
- Self::set_project_trust(&switch_path, project_cwd, trusted).await?;
-
match trusted {
true => Ok(()),
false => Err(Error::ProjectNotTrusted(project_cwd.clone())),You can send follow-ups to the cloud agent here.
Reviewed by Cursor Bugbot for commit e46e07c. Configure here.
| }, | ||
| }; | ||
|
|
||
| Self::set_project_trust(&switch_path, project_cwd, trusted).await?; |
There was a problem hiding this comment.
Redundant subprocess spawning while holding the lock
Low Severity
When concurrent build scripts all call check_project_trust before the first one persists trust, they all queue on the TRUST_PROMPT_RESULT lock. After the first task prompts and persists, subsequent tasks read the cached Some(trusted) value but still unconditionally call set_project_trust (line 662), spawning a redundant subprocess while holding the mutex. This serializes all pending scripts through unnecessary subprocess calls. The set_project_trust call could be limited to the None branch where the prompt actually happens, since the first caller already persists trust.
Reviewed by Cursor Bugbot for commit e46e07c. Configure here.
|
The push command requires write access to the repository. |



This diff implements the concept of trusted projects. When a project install would run a unsecure command, we now first check whether Yarn Switch trusts the root project folder. If it doesn't, we first prompt the user for confirmation that the folder should be trusted.
The intent of that PR is not to protect a trusted project against malicious postinstalls - that's what other settings like
enableScriptsornpmMinimalAgeGateare for. Instead we're trying here to solve the case where you'd run ayarn installon an untrusted project you downloaded in such a way that you'd end up executing arbitrary code. While not common amongst every user maintainers regularly do that when testing repros, and maintainers are very valuable targets.Note
High Risk
High risk because it changes when and whether install/build scripts are allowed to execute, adding new interactive prompting and CI-specific trust defaults that can affect automation and security posture.
Overview
Adds a per-project trust model to Yarn Switch and gates install-script execution on it. A new
switch trustcommand (--check/--set true|false|null) persists trust state per project folder and is used byzpmbefore running scripts, prompting interactively when trust is unknown and erroring when untrusted.Trust state is now stored alongside link data via a new
FolderConfigformat, exposed inswitch cacheoutput, and treated as implicitly trusted on CI unless explicitly untrusted. CI workflows/actions are updated to allow tests to run against a provided locally builtyarn-switchbinary, and new acceptance tests cover the trust command and script gating behavior.Reviewed by Cursor Bugbot for commit 7f2ebf4. Bugbot is set up for automated code reviews on this repo. Configure here.