Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/auth/secure-credential-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ export class SecureCredentialStore {
*/
private async initializeKeychain(): Promise<void> {
try {
// On Linux without a display session, libsecret's D-Bus call to the Secret
// Service blocks the Node.js event loop indefinitely — the keyring daemon is
// running but locked, and the GUI unlock dialog never appears in SSH/headless
// environments. Since @napi-rs/keyring uses native N-API (not async I/O),
// Promise.race cannot interrupt it. Bail out early instead.
if (process.platform === 'linux' && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY) {
this.keychainAvailable = false;
logger.debug('Skipping OS keychain: Linux without display (headless/SSH) — using encrypted file storage');
return;
Comment on lines +61 to +69
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title/description say a 3s timeout is added around the keychain test (and mention a "Keychain test timed out after 3000ms" debug message), but the implementation here instead unconditionally skips keychain initialization on Linux when DISPLAY/WAYLAND_DISPLAY are unset and does not implement any timeout. Either update the PR metadata/log expectations to match this behavior, or implement the promised timeout via a cancelable mechanism (e.g., run the keyring test in a worker/child process that can be terminated).

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +69
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change disables OS keychain usage for all Linux runs without DISPLAY/WAYLAND_DISPLAY, even if the Secret Service is already unlocked and usable in a headless session. Consider adding an explicit override (e.g., env var or config) to force keychain usage, so headless environments that do have a working keyring aren’t silently downgraded to encrypted-file storage.

Copilot uses AI. Check for mistakes.
}

// Dynamically import keyring
const keyring = await import('@napi-rs/keyring');
this.Entry = keyring.Entry;
Expand Down
Loading