mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-31 12:03:46 +00:00 
			
		
		
		
	export: Don't export DirectMessageGroup info of non-consented users.
This is private information, as by inspecting the DirectMessageGroup objects and their associated Subscription objects, you could determine which users conversed with each other in a DM group. This did *not* leak any actual message - only the fact that at least one of the users in the group sent a group DM.
This commit is contained in:
		
				
					committed by
					
						 Tim Abbott
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							0fd79e379e
						
					
				
				
					commit
					d098b9c349
				
			| @@ -1410,13 +1410,46 @@ def fetch_client_data(response: TableData, client_ids: set[int]) -> None: | |||||||
|  |  | ||||||
| def custom_fetch_direct_message_groups(response: TableData, context: Context) -> None: | def custom_fetch_direct_message_groups(response: TableData, context: Context) -> None: | ||||||
|     realm = context["realm"] |     realm = context["realm"] | ||||||
|  |     export_type = context["export_type"] | ||||||
|  |     exportable_user_ids_from_context = context["exportable_user_ids"] | ||||||
|  |  | ||||||
|  |     if export_type == RealmExport.EXPORT_FULL_WITH_CONSENT: | ||||||
|  |         assert exportable_user_ids_from_context is not None | ||||||
|  |         consented_user_ids = exportable_user_ids_from_context | ||||||
|  |     elif export_type == RealmExport.EXPORT_FULL_WITHOUT_CONSENT: | ||||||
|  |         assert exportable_user_ids_from_context is None | ||||||
|  |     else: | ||||||
|  |         assert export_type == RealmExport.EXPORT_PUBLIC | ||||||
|  |         consented_user_ids = set() | ||||||
|  |  | ||||||
|     user_profile_ids = { |     user_profile_ids = { | ||||||
|         r["id"] for r in response["zerver_userprofile"] + response["zerver_userprofile_mirrordummy"] |         r["id"] for r in response["zerver_userprofile"] + response["zerver_userprofile_mirrordummy"] | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     # First we get all direct message groups involving someone in the realm. |     recipient_filter = Q() | ||||||
|     realm_direct_message_group_subs = Subscription.objects.select_related("recipient").filter( |     if export_type != RealmExport.EXPORT_FULL_WITHOUT_CONSENT: | ||||||
|         recipient__type=Recipient.DIRECT_MESSAGE_GROUP, user_profile__in=user_profile_ids |         # First we find the set of recipient ids of DirectMessageGroups which can be exported. | ||||||
|  |         # A DirectMessageGroup can be exported only if at least one of its users is consenting | ||||||
|  |         # to the export of private data. | ||||||
|  |         # We can find this set by gathering all the Subscriptions of consenting users to | ||||||
|  |         # DirectMessageGroups and collecting the set of recipient_ids from those Subscriptions. | ||||||
|  |         exportable_direct_message_group_recipient_ids = set( | ||||||
|  |             Subscription.objects.filter( | ||||||
|  |                 recipient__type=Recipient.DIRECT_MESSAGE_GROUP, user_profile__in=consented_user_ids | ||||||
|  |             ) | ||||||
|  |             .distinct("recipient_id") | ||||||
|  |             .values_list("recipient_id", flat=True) | ||||||
|  |         ) | ||||||
|  |         recipient_filter = Q(recipient_id__in=exportable_direct_message_group_recipient_ids) | ||||||
|  |  | ||||||
|  |     # Now we fetch all the Subscription objects to the exportable DireMessageGroups in the realm. | ||||||
|  |     realm_direct_message_group_subs = ( | ||||||
|  |         Subscription.objects.select_related("recipient") | ||||||
|  |         .filter( | ||||||
|  |             recipient__type=Recipient.DIRECT_MESSAGE_GROUP, | ||||||
|  |             user_profile__in=user_profile_ids, | ||||||
|  |         ) | ||||||
|  |         .filter(recipient_filter) | ||||||
|     ) |     ) | ||||||
|     realm_direct_message_group_recipient_ids = { |     realm_direct_message_group_recipient_ids = { | ||||||
|         sub.recipient_id for sub in realm_direct_message_group_subs |         sub.recipient_id for sub in realm_direct_message_group_subs | ||||||
| @@ -1456,6 +1489,12 @@ def custom_fetch_direct_message_groups(response: TableData, context: Context) -> | |||||||
|     response["zerver_huddle"] = make_raw( |     response["zerver_huddle"] = make_raw( | ||||||
|         DirectMessageGroup.objects.filter(id__in=direct_message_group_ids) |         DirectMessageGroup.objects.filter(id__in=direct_message_group_ids) | ||||||
|     ) |     ) | ||||||
|  |     if export_type == RealmExport.EXPORT_PUBLIC and any( | ||||||
|  |         response[t] for t in ["_huddle_recipient", "_huddle_subscription", "zerver_huddle"] | ||||||
|  |     ): | ||||||
|  |         raise AssertionError( | ||||||
|  |             "Public export should not result in exporting any data in _huddle tables" | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
| def custom_fetch_scheduled_messages(response: TableData, context: Context) -> None: | def custom_fetch_scheduled_messages(response: TableData, context: Context) -> None: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user