fix(app): remove plaintext fallback from key vault when crypto unavailable
storeApiKey() now throws when encryption is not available instead of storing keys in plaintext. ApiKeyManager.vue catches the error and displays a warning message. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
5c4afe00e5
commit
6720711302
@@ -136,12 +136,17 @@ async function loadProviders() {
|
||||
|
||||
async function saveKey() {
|
||||
if (!selectedProvider.value || !newKey.value.trim()) return
|
||||
await storeApiKey(selectedProvider.value, newKey.value.trim())
|
||||
statusMessage.value = `${PROVIDER_NAMES[selectedProvider.value] ?? selectedProvider.value} key saved`
|
||||
statusError.value = false
|
||||
newKey.value = ''
|
||||
selectedProvider.value = ''
|
||||
await loadProviders()
|
||||
try {
|
||||
await storeApiKey(selectedProvider.value, newKey.value.trim())
|
||||
statusMessage.value = `${PROVIDER_NAMES[selectedProvider.value] ?? selectedProvider.value} key saved`
|
||||
statusError.value = false
|
||||
newKey.value = ''
|
||||
selectedProvider.value = ''
|
||||
await loadProviders()
|
||||
} catch (err) {
|
||||
statusMessage.value = err instanceof Error ? err.message : 'Failed to store key — encryption required'
|
||||
statusError.value = true
|
||||
}
|
||||
}
|
||||
|
||||
async function removeKey(provider: string) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Encrypted API key vault using IndexedDB + AES-256-GCM.
|
||||
* Keys are encrypted with the session key derived from passphrase.
|
||||
* Falls back to plaintext storage when crypto is disabled (dev mode).
|
||||
* Refuses to store keys when encryption is unavailable.
|
||||
*/
|
||||
import {
|
||||
isCryptoEnabled,
|
||||
@@ -38,13 +38,13 @@ export async function storeApiKey(provider: string, key: string): Promise<void>
|
||||
if (typeof indexedDB === 'undefined') return
|
||||
const db = await openDB()
|
||||
const sessionKey = getSessionKey()
|
||||
const useEncryption = isCryptoEnabled() && !!sessionKey
|
||||
|
||||
const value = useEncryption
|
||||
? await encryptToString(key, sessionKey!)
|
||||
: key
|
||||
if (!isCryptoEnabled() || !sessionKey) {
|
||||
throw new Error('Encryption required: cannot store API keys without an active session key. Please set a passphrase first.')
|
||||
}
|
||||
|
||||
const record: VaultRecord = { provider, value, encrypted: useEncryption }
|
||||
const value = await encryptToString(key, sessionKey)
|
||||
const record: VaultRecord = { provider, value, encrypted: true }
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const tx = db.transaction(STORE_NAME, 'readwrite')
|
||||
|
||||
Reference in New Issue
Block a user