mirror of
https://github.com/block/buzz.git
synced 2026-11-13 04:41:12 +00:00
fix(relay): fail-visible on DB error resolving approval-note channel
enforce_latched_approval_note swallowed every get_workflow error via .ok(), collapsing a transient DB error to None and skipping the latch check. A PgPool blip during channel resolution would let a plaintext approval note reach a latched DM — the leak this PR closes, reopened on the security boundary itself. Match enforce_latched_body's posture: NotFound passes (no resolvable channel, cannot be latched), any other DbError is fail-visible. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
committed by
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7
parent
869685243e
commit
6604d5882e
@@ -120,18 +120,22 @@ async fn enforce_latched_body(
|
||||
/// latched-body rule on the approval note. Approvals reference no `h` tag of
|
||||
/// their own — the channel is the workflow's (`get_workflow().channel_id`).
|
||||
/// A workflow with no channel (global) cannot be latched, so it passes through.
|
||||
///
|
||||
/// The `get_workflow` lookup honors the same fail-VISIBLE posture as
|
||||
/// [`enforce_latched_body`]: a missing workflow (`NotFound`) cannot be latched
|
||||
/// and passes, but a genuine DB error rejects rather than silently skipping the
|
||||
/// check — otherwise a transient pool blip would let a plaintext note slip into
|
||||
/// a latched channel.
|
||||
async fn enforce_latched_approval_note(
|
||||
state: &Arc<AppState>,
|
||||
content: &str,
|
||||
workflow_id: Uuid,
|
||||
) -> Result<(), IngestError> {
|
||||
let channel_id = state
|
||||
.db
|
||||
.get_workflow(workflow_id)
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|w| w.channel_id);
|
||||
enforce_latched_body(state, content, channel_id).await
|
||||
match state.db.get_workflow(workflow_id).await {
|
||||
Ok(w) => enforce_latched_body(state, content, w.channel_id).await,
|
||||
Err(buzz_db::DbError::NotFound(_)) => Ok(()),
|
||||
Err(e) => Err(IngestError::Rejected(format!("error: database error: {e}"))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Persist a command event inside a transaction. Returns the OPEN transaction
|
||||
|
||||
Reference in New Issue
Block a user