From 882f69cbaf0f851717f071fba366b3b3a4a877d8 Mon Sep 17 00:00:00 2001 From: Logan Johnson Date: Sat, 5 Sep 2026 17:42:31 -0400 Subject: [PATCH] fix(mobile): reject stale destination membership fallback Signed-off-by: Logan Johnson --- mobile/lib/shared/mentions/agent_authorization.dart | 13 +++++++++---- .../shared/mentions/agent_authorization_test.dart | 8 +++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/mobile/lib/shared/mentions/agent_authorization.dart b/mobile/lib/shared/mentions/agent_authorization.dart index 8e6f90998a..ec6e2438cd 100644 --- a/mobile/lib/shared/mentions/agent_authorization.dart +++ b/mobile/lib/shared/mentions/agent_authorization.dart @@ -46,9 +46,7 @@ Future> readAgentAuthorization( check(); final latest = {}; for (final event in membership) { - if (event.kind != 39002 || - event.pubkey != authority || - !verifySignedEvent(event)) { + if (event.kind != 39002 || event.pubkey != authority) { continue; } final destination = event.getTagValue('d'); @@ -66,6 +64,13 @@ Future> readAgentAuthorization( final owned = agent.ownerPubkey == viewer; final channels = []; for (final entry in latest.entries) { + if (!verifySignedEvent(entry.value) || + entry.value.tags + .where((tag) => tag.isNotEmpty && tag[0] == 'd') + .length != + 1) { + continue; + } final people = entry.value.tags.where( (tag) => tag.length >= 2 && tag[0] == 'p', ); @@ -109,7 +114,7 @@ Future> _membershipPages( kinds: const [39002], authors: [authority], tags: { - '#p': [viewer], + if (channelId == null) '#p': [viewer], if (channelId != null) '#d': [channelId], }, limit: 500, diff --git a/mobile/test/shared/mentions/agent_authorization_test.dart b/mobile/test/shared/mentions/agent_authorization_test.dart index 216a501cd8..6d5fc8c06f 100644 --- a/mobile/test/shared/mentions/agent_authorization_test.dart +++ b/mobile/test/shared/mentions/agent_authorization_test.dart @@ -99,7 +99,6 @@ void main() { final filter = session.queries.first; expect(filter.authors, [relay.public]); expect(filter.tags, { - '#p': [owner.public], '#d': ['room'], }); expect( @@ -133,6 +132,13 @@ void main() { NostrEvent.fromJson({...members().toJson(), 'content': 'tampered'}), ], [members(), members(time: 101, includeAgent: false)], + [ + members(), + NostrEvent.fromJson({ + ...members(time: 101).toJson(), + 'content': 'tampered', + }), + ], [members(), members(time: 101, includeViewer: false)], ]) { final result = await read(