fix(secrets): explain Linux basic_text storage fallback#2651
fix(secrets): explain Linux basic_text storage fallback#2651rasitakyol wants to merge 2 commits into
Conversation
Greptile SummaryThis PR improves the Linux
Confidence Score: 4/5Safe to merge — the only code change is an extended error message with no logic alterations. The source change is minimal and entirely contained to the error string. The new test exercises apps/emdash-desktop/src/main/core/secrets/encrypted-app-secrets-store.test.ts — the
|
| Filename | Overview |
|---|---|
| apps/emdash-desktop/src/main/core/secrets/encrypted-app-secrets-store.ts | Error message for Linux basic_text backend extended with actionable fix instructions; logic is unchanged. |
| apps/emdash-desktop/src/main/core/secrets/encrypted-app-secrets-store.test.ts | New test file covering the basic_text rejection path for setSecret; getSecret on the same failure path is not covered. |
| README.md | Adds Linux keyring prerequisite note pointing users to GNOME libsecret and the --password-store flag. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[setSecret / getSecret called] --> B{isEncryptionAvailable?}
B -- No --> C[throw: Secure secret storage is unavailable]
B -- Yes --> D{platform === 'linux'?}
D -- No --> E[proceed with encrypt/decrypt]
D -- Yes --> F{getSelectedStorageBackend?}
F -- 'basic_text' --> G["throw: Install GNOME libsecret\nor use --password-store=gnome-libsecret"]
F -- other e.g. 'os_crypt' --> E
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[setSecret / getSecret called] --> B{isEncryptionAvailable?}
B -- No --> C[throw: Secure secret storage is unavailable]
B -- Yes --> D{platform === 'linux'?}
D -- No --> E[proceed with encrypt/decrypt]
D -- Yes --> F{getSelectedStorageBackend?}
F -- 'basic_text' --> G["throw: Install GNOME libsecret\nor use --password-store=gnome-libsecret"]
F -- other e.g. 'os_crypt' --> E
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
apps/emdash-desktop/src/main/core/secrets/encrypted-app-secrets-store.test.ts:25-39
**`getSecret` `basic_text` path not exercised**
The test verifies that `setSecret` rejects before calling `encryptString` when the backend is `basic_text`, but `getSecret` also calls `assertSecureStorageAvailable` and would likewise throw on a `basic_text` Linux system. A user retrieving a previously-stored credential on an affected machine hits exactly this path. Adding a parallel assertion for `getSecret` (with a mocked DB row) would give the same safety net as the `setSecret` case and ensure both read and write paths are guarded by the improved error message.
Reviews (1): Last reviewed commit: "fix(secrets): explain Linux basic_text s..." | Re-trigger Greptile
| describe('EncryptedAppSecretsStore', () => { | ||
| it('explains how to fix Linux basic_text secure storage fallback', async () => { | ||
| const safeStorageApi = { | ||
| isEncryptionAvailable: () => true, | ||
| encryptString: vi.fn((value: string) => Buffer.from(value)), | ||
| decryptString: vi.fn((value: Buffer) => value.toString('utf8')), | ||
| getSelectedStorageBackend: () => 'basic_text', | ||
| }; | ||
| const store = new EncryptedAppSecretsStore({} as never, safeStorageApi as never, 'linux'); | ||
|
|
||
| await expect(store.setSecret('token', 'secret')).rejects.toThrow( | ||
| '--password-store=gnome-libsecret' | ||
| ); | ||
| expect(safeStorageApi.encryptString).not.toHaveBeenCalled(); | ||
| }); |
There was a problem hiding this comment.
getSecret basic_text path not exercised
The test verifies that setSecret rejects before calling encryptString when the backend is basic_text, but getSecret also calls assertSecureStorageAvailable and would likewise throw on a basic_text Linux system. A user retrieving a previously-stored credential on an affected machine hits exactly this path. Adding a parallel assertion for getSecret (with a mocked DB row) would give the same safety net as the setSecret case and ensure both read and write paths are guarded by the improved error message.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/emdash-desktop/src/main/core/secrets/encrypted-app-secrets-store.test.ts
Line: 25-39
Comment:
**`getSecret` `basic_text` path not exercised**
The test verifies that `setSecret` rejects before calling `encryptString` when the backend is `basic_text`, but `getSecret` also calls `assertSecureStorageAvailable` and would likewise throw on a `basic_text` Linux system. A user retrieving a previously-stored credential on an affected machine hits exactly this path. Adding a parallel assertion for `getSecret` (with a mocked DB row) would give the same safety net as the `setSecret` case and ensure both read and write paths are guarded by the improved error message.
How can I resolve this? If you propose a fix, please make it concise.
Summary
basic_textsecure-storage failure actionable by pointing users to GNOME libsecret /--password-store=gnome-libsecretbasic_textfailure pathRefs #1875
Test Plan
pnpm --dir apps/emdash-desktop exec vitest run --project node src/main/core/secrets/encrypted-app-secrets-store.test.tspnpm --filter @emdash/emdash-desktop run format:checkpnpm --filter @emdash/emdash-desktop run typecheck