Why
CodeQL alert #5 (js/clear-text-storage-of-sensitive-data) confirms a known security debt: saveReviewConfig serializes gatewayApiKey into browser localStorage. The desktop-only threat model reduces remote exposure but does not protect the credential from webview compromise, localStorage export, or local inspection.
Requirement
Provider credentials must be stored through an OS-backed credential boundary and must never be serialized into localStorage, SQLite, logs, analytics, review receipts, or MCP output. Non-secret provider settings and standards packs may remain in localStorage.
Design constraints
- Preserve existing Anthropic, OpenAI, and OpenRouter behavior.
- Provide an explicit migration path that removes the legacy localStorage key after a successful credential-store write.
- Fail closed if secure storage is unavailable; do not silently fall back to plaintext persistence.
- Keep browser-mode behavior explicit and non-persistent.
- Any new production dependency requires owner review of maintenance, licensing, signing/notarization, and platform support before adoption.
- Add tests for migration, absence of serialized credentials, unavailable storage, update, and deletion.
Acceptance
Evidence
Why
CodeQL alert #5 (
js/clear-text-storage-of-sensitive-data) confirms a known security debt:saveReviewConfigserializesgatewayApiKeyinto browser localStorage. The desktop-only threat model reduces remote exposure but does not protect the credential from webview compromise, localStorage export, or local inspection.Requirement
Provider credentials must be stored through an OS-backed credential boundary and must never be serialized into localStorage, SQLite, logs, analytics, review receipts, or MCP output. Non-secret provider settings and standards packs may remain in localStorage.
Design constraints
Acceptance
Evidence
apps/desktop/src/lib/review-service.ts(saveReviewConfig).