Revert "connectd: gate uniform message padding behind --dev-uniform-padding"
What changed, and why it matters
This commit removes a developer-only flag that made message padding optional, restoring uniform padding for all encrypted peer messages. Uniform padding hides the real length of messages, so reverting to always-on padding is a privacy improvement rather than a security bug. There is no direct evidence this change fixes an active vulnerability; it appears to be a design cleanup that strengthens traffic-analysis resistance.
Treat as a privacy-hardening cleanup. Review whether the original --dev-uniform-padding flag was documented or used in production, and update release notes to note that uniform padding is now mandatory. No urgent patch cycle is required unless additional context shows the optional padding caused a concrete vulnerability.
Security signals we found
Reverts a feature flag so privacy-hardening behavior is no longer optional
Always pads encrypted messages to a fixed size, reducing traffic-analysis leakage
Removes a developer-only option that could weaken message-length privacy
No buffer overflow, use-after-free, or authentication bypass visible in diff
Evidence from the diff
The patch reverts an earlier change (b5205f5) that gated uniform message padding behind –dev-uniform-padding. After this revert, connectd/multiplex.c always pads encrypted peer output to UNIFORM_MESSAGE_SIZE and always writes a full chunk, regardless of the dev flag. This removes the ability to run without padding and deletes the conditional branches and early-empty-queue path that existed for the non-padded case.
Changed components
connectd/multiplex.cpeer message encryption/padding pathUNIFORM_MESSAGE_SIZE write pathInspect captured patch +4 / −21
diff --git a/connectd/multiplex.c b/connectd/multiplex.c
index 57a74be4..0c5b0e4f 100644
--- a/connectd/multiplex.c
+++ b/connectd/multiplex.c
@@ -485,16 +485,10 @@ static bool have_empty_encrypted_queue(const struct peer *peer)
/* (Continue) writing the encrypted_peer_out array */
static struct io_plan *write_encrypted_to_peer(struct peer *peer)
{
- size_t avail = membuf_num_elems(&peer->encrypted_peer_out);
- /* With padding: always a full uniform-size chunk.
- * Without: flush whatever we have (caller ensures non-zero). */
- size_t write_size = peer->daemon->dev_uniform_padding
- ? UNIFORM_MESSAGE_SIZE : avail;
-
- assert(avail >= write_size && write_size > 0);
+ assert(membuf_num_elems(&peer->encrypted_peer_out) >= UNIFORM_MESSAGE_SIZE);
return io_write_partial(peer->to_peer,
membuf_elems(&peer->encrypted_peer_out),
- write_size,
+ UNIFORM_MESSAGE_SIZE,
&peer->encrypted_peer_out_sent,
write_to_peer, peer);
}
@@ -1251,11 +1245,8 @@ static struct io_plan *write_to_peer(struct io_conn *peer_conn,
/* Wait for them to wake us */
return msg_queue_wait(peer_conn, peer->peer_outq, write_to_peer, peer);
}
- /* OK, add padding (only if --dev-uniform-padding enabled). */
- if (peer->daemon->dev_uniform_padding)
- pad_encrypted_queue(peer);
- else
- break;
+ /* OK, add padding. */
+ pad_encrypted_queue(peer);
} else {
if (peer->draining_state == WRITING_TO_PEER)
status_peer_debug(&peer->id, "draining, but sending %s.",
@@ -1273,14 +1264,6 @@ static struct io_plan *write_to_peer(struct io_conn *peer_conn,
}
peer->nonurgent_flush_timer = tal_free(peer->nonurgent_flush_timer);
-
- /* With uniform padding the buffer is always a full UNIFORM_MESSAGE_SIZE.
- * Without it, write whatever we have; if nothing, go back to waiting. */
- if (have_empty_encrypted_queue(peer)) {
- io_wake(&peer->subds);
- io_wake(&peer->peer_in);
- return msg_queue_wait(peer_conn, peer->peer_outq, write_to_peer, peer);
- }
return write_encrypted_to_peer(peer);
}
Why this scored 34/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.