Docs

Secure storage (window.Electron.secureStorage)

Encrypted key/value storage, backed by Electron's OS-level safeStorage (Keychain / DPAPI / libsecret) plus a JSON file on disk. Source: src/main/secure-storage.ts, channel prefix secureStorage:*. Always on, no config needed — see Security configuration for the security.secureStorageKeys key-hashing option this module reads.

safeStorage only encrypts/decrypts individual strings — it isn't a database — so this module layers a plain JSON file at {userData}/secure-storage.json underneath it, with each value individually encrypted before being written. Every read-modify-write cycle (set/remove/clear) is queued through one promise chain per process, so two calls in a row can't silently clobber each other.

Methods

Method Returns Notes
isEncryptionAvailable() Promise<boolean> Whether the OS backend (Keychain/DPAPI/libsecret) is actually available.
getSelectedStorageBackend() Promise<string> The OS backend Electron picked, when queryable; falls back to process.platform.
set(key: string, value: string) Promise<void> Throws VALIDATION if key is empty.
get(key: string) Promise<string | null> null when the key doesn't exist. Throws VALIDATION if key is empty.
remove(key: string) Promise<void>
clear() Promise<void> Wipes the whole store.
keys() Promise<string[]> Throws NOT_CONFIGURED when security.secureStorageKeys is 'hashed' — see below.
encryptString(value: string) Promise<string> One-off encryption without persisting to the store.
decryptString(value: string) Promise<string> Inverse of encryptString.

Key hashing (security.secureStorageKeys)

'plain' (default) keeps your original key names on disk — only the values are encrypted. 'hashed' stores a deterministic SHA-256 hash of ${appId}:${key} instead of the original name. In hashed mode, keys() always rejects with NOT_CONFIGURED rather than returning a list of unusable hashes — get()/remove() still work because they re-hash the key you pass in, but there's no way to recover the original names from what's stored. Existing data is not migrated automatically if you switch modes mid-project.

Example

await window.Electron.secureStorage.set('authToken', token);
const stored = await window.Electron.secureStorage.get('authToken'); // string | null
await window.Electron.secureStorage.remove('authToken');

.safe

Fully mirrored — window.Electron.safe.secureStorage.* resolves { ok: true, data } / { ok: false, error } instead of throwing. Useful for keys() specifically, since checking result.error.code === 'NOT_CONFIGURED' avoids a try/catch just to detect hashed-key mode.

Last updated on July 18, 2026