fix(federation): add strict origin enforcement for user attribution (FED-010)

Prevent malicious peers from forging events attributed to users on other
instances. Every relay event processor now verifies the acting user's
homeInstance (from payload) matches X-Federation-Origin (from HMAC-verified
header) via verifyAttribution(), normalized to bare domain.

- Add verifyAttribution() helper using extractDomain normalization
- Guard all 13 event processors before any user resolution or DB writes
- Add homeInstance to FederationRelayReaction type + outbound payloads
- Replace unnormalized string equality in friend handlers
- Log mismatched values on rejection for debugging
This commit is contained in:
Jannis Braun
2026-03-31 19:16:48 +02:00
parent d0ed43cf58
commit 720a5de945
4 changed files with 101 additions and 18 deletions
+4
View File
@@ -1134,6 +1134,7 @@ function handleReactionAdd(event: Record<string, unknown>, userId: string): void
appendMutationLog(messageId, dmMsg.dmChannelId, 'reaction_add', JSON.stringify({
userId,
homeUserId: reactionUser?.homeUserId || userId,
homeInstance: reactionUser?.homeInstance || getOurOrigin(),
emoji,
createdAt: now,
}));
@@ -1144,6 +1145,7 @@ function handleReactionAdd(event: Record<string, unknown>, userId: string): void
messageHomeInstance,
userId,
homeUserId: reactionUser?.homeUserId || userId,
homeInstance: reactionUser?.homeInstance || getOurOrigin(),
emoji,
createdAt: now,
},
@@ -1213,6 +1215,7 @@ function handleReactionRemove(event: Record<string, unknown>, userId: string): v
appendMutationLog(messageId, dmMsg.dmChannelId, 'reaction_remove', JSON.stringify({
userId,
homeUserId: removingUser?.homeUserId || userId,
homeInstance: removingUser?.homeInstance || getOurOrigin(),
emoji,
}));
const reactionRemoveTargetOrigins = getGroupDmTargetOrigins(dmMsg.dmChannelId);
@@ -1226,6 +1229,7 @@ function handleReactionRemove(event: Record<string, unknown>, userId: string): v
messageHomeInstance,
userId,
homeUserId: removingUser?.homeUserId || userId,
homeInstance: removingUser?.homeInstance || getOurOrigin(),
emoji,
},
}),