From ceaa08b4bd7802a58974fded926212719f51d967 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Tue, 21 Apr 2026 20:49:19 +0200 Subject: [PATCH] fix(federation): extend /peer/accept safeguard to cover needs_attention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unauthenticated /peer/accept must not overwrite hmac_secret for peers in needs_attention, same as active. needs_attention means 'auth trust broke and we don't know why' — letting an unauthenticated request flip it back would reintroduce a path for silent HMAC rotation via the outbox-401 loop the rest of #19 closes. Legitimate recovery is the admin 'Reset peering' action (next task). --- packages/server/src/routes/federation.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/server/src/routes/federation.ts b/packages/server/src/routes/federation.ts index e12b7857..e0a21f6b 100644 --- a/packages/server/src/routes/federation.ts +++ b/packages/server/src/routes/federation.ts @@ -491,8 +491,17 @@ export async function federationRoutes(app: FastifyInstance): Promise { .get(); if (existing) { - if (existing.status === 'active') { - // Idempotent — already peered + if (existing.status === 'active' || existing.status === 'needs_attention') { + // Idempotent — already peered (or peering is in needs_attention state). + // In both cases we refuse to overwrite hmac_secret via this + // unauthenticated endpoint. An unauthenticated caller cannot + // prove prior trust, and needs_attention means "we don't know + // why this broke" — letting an unauthenticated request flip it + // to active with a new secret defeats the purpose. + // + // Legitimate recovery path: local admin clicks "Reset peering" → + // row is deleted → remote's /peer/accept then lands on a + // non-existent row and the normal handshake path runs. return reply.code(200).send({ accepted: true }); } if (existing.status === 'revoked') {