Skip to content

Harden database keyring error handling and key persistence #194

Description

@BillyOutlast

Source

PR #191 review threads:

Problems

  1. Ephemeral key never persisted: When keyring::Entry::new fails, a random ephemeral key is generated and returned but never saved. On next startup, if keyring works again, a different key is used → old data permanently unreadable.

  2. copy_from_slice panics: key.copy_from_slice(&secret) crashes at runtime if keyring returns secret of wrong length.

  3. set_secret panics: After generating a new random key, if keyring write fails, the key is lost → data loss on next startup.

  4. All keyring errors treated as NoEntry: get_secret().unwrap_or_else(...) rotates the key for PlatformFailure and Ambiguous errors, not just missing entries. Should distinguish NoEntry (generate new key) from other errors (surface/propagate).

Fix

// 1. Validate secret length before copy
if secret.len() != 32 { anyhow::bail!(...) }

// 2. Distinguish NoEntry from other errors on get_secret
match entry.get_secret() {
    Ok(secret) => { /* normal flow */ }
    Err(keyring::Error::NoEntry) => { /* generate + persist new key */ }
    Err(e) => { anyhow::bail!("keyring read error: {e}") }
}

// 3. Handle set_secret failure
entry.set_secret(&buffer).map_err(|e| anyhow::anyhow!("failed to save key: {e}"))?;

// 4. On keyring init failure, bail instead of generating ephemeral key
// (or persist ephemeral to filesystem as fallback)

Relates: #191

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions