Surfaced during M6-S1 (#198), which fixed the WRITE-path silent-empty bug in encrypt_text_at_rest. The symmetric READ path, PayloadCipher::decrypt_text_at_rest (crates/nuncio-store/src/cipher.rs), still silently returns "" on any hex-decode / AEAD-decrypt / UTF-8 failure — so a genuinely corrupted or tamper-detected body column reads back as an empty body rather than surfacing an error. That defeats the AEAD's integrity guarantee at the point it matters most (detecting tampering/corruption on read).
Fix: make decrypt_text_at_rest fail closed too — return Result and propagate decode/decrypt/UTF-8 errors instead of .unwrap_or_default()/.ok(). Update the read call sites in db.rs (get_message / list paths) to propagate as a DatabaseError variant. Add a test that a corrupted ciphertext column surfaces an error, not an empty string. Non-proto. Companion to #198/#162. Candidate for the M6 security milestone.
Surfaced during M6-S1 (#198), which fixed the WRITE-path silent-empty bug in `encrypt_text_at_rest`. The symmetric READ path, `PayloadCipher::decrypt_text_at_rest` (`crates/nuncio-store/src/cipher.rs`), still silently returns `""` on any hex-decode / AEAD-decrypt / UTF-8 failure — so a genuinely corrupted or tamper-detected body column reads back as an empty body rather than surfacing an error. That defeats the AEAD's integrity guarantee at the point it matters most (detecting tampering/corruption on read).
Fix: make `decrypt_text_at_rest` fail closed too — return `Result` and propagate decode/decrypt/UTF-8 errors instead of `.unwrap_or_default()`/`.ok()`. Update the read call sites in `db.rs` (get_message / list paths) to propagate as a `DatabaseError` variant. Add a test that a corrupted ciphertext column surfaces an error, not an empty string. Non-proto. Companion to #198/#162. Candidate for the M6 security milestone.
Delivered via PR #264 (squash-merged to dev). decrypt_text_at_rest now returns Result and fails closed on hex-decode/AEAD-decrypt/UTF-8 failure (new DatabaseError::Decryption variant); all 5 read call sites (get_message, list_messages, get_message_chunk, list_messages_for_export, backfill_message_fts) propagate the error instead of returning a silently-empty body. A corrupted/tampered ciphertext now surfaces an error on read rather than defeating the AEAD integrity guarantee. Companion to #198/#162.
Delivered via PR #264 (squash-merged to dev). decrypt_text_at_rest now returns Result and fails closed on hex-decode/AEAD-decrypt/UTF-8 failure (new DatabaseError::Decryption variant); all 5 read call sites (get_message, list_messages, get_message_chunk, list_messages_for_export, backfill_message_fts) propagate the error instead of returning a silently-empty body. A corrupted/tampered ciphertext now surfaces an error on read rather than defeating the AEAD integrity guarantee. Companion to #198/#162.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Surfaced during M6-S1 (#198), which fixed the WRITE-path silent-empty bug in
encrypt_text_at_rest. The symmetric READ path,PayloadCipher::decrypt_text_at_rest(crates/nuncio-store/src/cipher.rs), still silently returns""on any hex-decode / AEAD-decrypt / UTF-8 failure — so a genuinely corrupted or tamper-detected body column reads back as an empty body rather than surfacing an error. That defeats the AEAD's integrity guarantee at the point it matters most (detecting tampering/corruption on read).Fix: make
decrypt_text_at_restfail closed too — returnResultand propagate decode/decrypt/UTF-8 errors instead of.unwrap_or_default()/.ok(). Update the read call sites indb.rs(get_message / list paths) to propagate as aDatabaseErrorvariant. Add a test that a corrupted ciphertext column surfaces an error, not an empty string. Non-proto. Companion to #198/#162. Candidate for the M6 security milestone.Delivered via PR #264 (squash-merged to dev). decrypt_text_at_rest now returns Result and fails closed on hex-decode/AEAD-decrypt/UTF-8 failure (new DatabaseError::Decryption variant); all 5 read call sites (get_message, list_messages, get_message_chunk, list_messages_for_export, backfill_message_fts) propagate the error instead of returning a silently-empty body. A corrupted/tampered ciphertext now surfaces an error on read rather than defeating the AEAD integrity guarantee. Companion to #198/#162.