-
Notifications
You must be signed in to change notification settings - Fork 2.5k
fix: macOS keychain infinite prompt loop #6620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be very nice @codefromthecrypt looks ok to you (once it is a clean build)
Signed-off-by: sheikhlimon <sheikhlimon404@gmail.com>
172618d to
5f18f7b
Compare
Signed-off-by: sheikhlimon <sheikhlimon404@gmail.com>
Signed-off-by: sheikhlimon <sheikhlimon404@gmail.com>
codefromthecrypt
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TL;DR; Thanks for doing this. Only main thing to pay attention to is a lazy loading race, and let me know if I'm off on it. Otherwise, looks good.
I think if we wanted to do a super clean job it would be refactoring to a real loading cache like moka, and/or concurrent tests like loom, but that's probably over solving and I like your stepping in cautiously.
For this code.. I think there's a potential lazy loading race (e.g., multiple threads could check None outside the lock and all try to load, causing redundant hits). Something like this might fix it (didn't try it, but should serialize the load):
pub fn all_secrets(&self) -> Result<HashMap<String, Value>, ConfigError> {
let mut cache = self.secrets_cache.lock().unwrap();
let values = if let Some(ref cached) = *cache {
cached.clone()
} else {
let loaded = match &self.secrets {
SecretStorage::Keyring { service } => { /* ... load ... */ },
SecretStorage::File { path } => self.read_secrets_from_file(path)?,
};
*cache = Some(loaded.clone());
loaded
};
Ok(values)
}Also, if you wanted to test this you could add instrumentation like a test-only SecretStorage.load_count: Arc<Mutex<u32>> (increment on load), then in a unit test simulate multiple get_secret calls (maybe even in threads) and assert only 1 load happened. Again, that's not full parallel testing, but low hanging fruit.
Signed-off-by: sheikhlimon <sheikhlimon404@gmail.com>
Signed-off-by: sheikhlimon <sheikhlimon404@gmail.com>
Signed-off-by: sheikhlimon <sheikhlimon404@gmail.com>
Thanks for reviewing this! I’ve implemented your suggested fix by holding the lock across the entire cache check and load operation. |
|
thanks again for the help! |
Signed-off-by: sheikhlimon <sheikhlimon404@gmail.com> Signed-off-by: fbalicchia <fbalicchia@cuebiq.com>
* origin/main: Fix GCP Vertex AI global endpoint support for Gemini 3 models (#6187) fix: macOS keychain infinite prompt loop (#6620) chore: reduce duplicate or unused cargo deps (#6630) feat: codex subscription support (#6600) smoke test allow pass for flaky providers (#6638) feat: Add built-in skill for goose documentation reference (#6534) Native images (#6619) docs: ml-based prompt injection detection (#6627) Strip the audience for compacting (#6646) chore(release): release version 1.21.0 (minor) (#6634) add collapsable chat nav (#6649) fix: capitalize Rust in CONTRIBUTING.md (#6640) chore(deps): bump lodash from 4.17.21 to 4.17.23 in /ui/desktop (#6623) Vibe mcp apps (#6569) Add session forking capability (#5882) chore(deps): bump lodash from 4.17.21 to 4.17.23 in /documentation (#6624) fix(docs): use named import for globby v13 (#6639) PR Code Review (#6043) fix(docs): use dynamic import for globby ESM module (#6636) # Conflicts: # Cargo.lock # crates/goose-server/src/routes/session.rs
Summary
Problem: Each call to
get_secret()hits keychain separately, causing multiple prompts when loading provider config with multiple secret parameters.Solution: Add in-memory cache to
all_secrets()so keychain is accessed once per config load.Type of Change
AI Assistance
Related Issues
Fixes #6595