Data portability (GDPR Art. 20) entitles users to their own data — not other users' data. An export query that fetches entire conversation threads by conversation ID rather than by participant ID will return messages the requesting user received from, or in group threads containing, other users who did not request the export. This is a direct CWE-285 (improper authorization) and CWE-200 (information exposure) violation, and a data breach reportable under GDPR Art. 33 if it reaches the requesting user's device.
Medium because the scope of exposure is bounded to conversation participants whose messages the user had legitimate access to read, but the export still violates their right to control their own data copy.
Filter the message export query strictly to rows where the requesting user is sender or recipient — never by conversation ID alone. In your data export job (src/jobs/generateDataExport.ts):
const messages = await db.message.findMany({
where: {
OR: [
{ senderId: userId },
{ recipientId: userId }
]
},
select: {
id: true, content: true, sentAt: true,
senderId: true, recipientId: true
}
});
// Do NOT query by conversationId — that pulls all participants' messages
Code-review the export job whenever the message schema changes to ensure new join tables or group-chat expansions don't reintroduce the over-fetch pattern.
ID: community-privacy-controls.data-rights.export-excludes-private-messages
Severity: medium
What to look for: Enumerate every relevant item. Examine data export logic. Check which messages are included — should include sent and received messages from the exporting user only, but NOT entire conversation threads from other users' inboxes. Verify the query excludes messages where the user is not a sender or recipient.
Pass criteria: At least 1 of the following conditions is met. Data export includes messages where the requesting user is the sender or recipient. Does not include messages from other users' conversations that the requester was not part of. Each user can only export their own message history.
Fail criteria: Export includes other users' private message conversations that the requester was not part of. Export grants access to message threads the user shouldn't see.
Skip (N/A) when: Never — data isolation is fundamental.
Detail on fail: Example: "Data export includes entire message threads from users the requester was not communicating with."
Remediation: Filter export to requester's own messages:
async function generateDataExport(userId: string) {
const messages = await db.message.findMany({
where: {
OR: [
{ senderId: userId },
{ recipientId: userId }
]
}
});
// NOT this (wrong):
// const messages = await db.message.findMany({
// where: { conversationId: { in: userConversations } }
// });
return { messages };
}