Deleting a user record while leaving their posts and comments attributed to the original user ID or username is a partial erasure that violates GDPR Art. 17. The username on a comment thread is PII — it identifies the person even after account deletion. CWE-212 (improper cross-boundary removal of sensitive data) captures this exact failure mode. Inconsistent handling across content types — posts anonymized but comments not, or media files left with original paths — compounds the exposure.
High because content that retains original attribution after account deletion constitutes continuing PII exposure in violation of GDPR Art. 17, even if the user record itself was removed.
Maintain a system-level DELETED_USER placeholder account and reassign all content to it atomically in the same transaction as the user row deletion. Handle every content type — posts, comments, likes, media, social graph edges — in a single function.
// src/lib/users/deleteContent.ts
async function deleteUserContent(userId: string) {
const ghost = await db.user.findUniqueOrThrow({ where: { username: 'DELETED_USER' } });
await db.$transaction([
db.post.updateMany({ where: { authorId: userId }, data: { authorId: ghost.id } }),
db.comment.updateMany({ where: { authorId: userId }, data: { authorId: ghost.id } }),
db.like.deleteMany({ where: { userId } }),
db.follow.deleteMany({ where: { OR: [{ followerId: userId }, { followingId: userId }] } }),
]);
}
If posts should be removed rather than preserved (forum vs. social context), swap updateMany for deleteMany, but choose one strategy and apply it consistently across all content types.
ID: community-privacy-controls.data-rights.deleted-content-handling
Severity: high
What to look for: Enumerate every relevant item. Check how deleted user content is handled. When a user is deleted, does their content (posts, comments) get removed or reassigned? Look for logic that orphans content, deletes it cascade-style, or attributs it to a "Deleted User" placeholder. Verify this is applied consistently across all content types.
Pass criteria: At least 1 of the following conditions is met. Deleted user content is either completely removed or attributed to an anonymized placeholder (e.g., "Deleted User" with no identifying info). Comments on others' posts, forum posts, and media are handled consistently. Relationships (likes, follows) are cleaned up.
Fail criteria: Deleted user content remains with the original user ID or username visible. Profile data is removed but content persists with broken references. Inconsistent handling across different content types.
Skip (N/A) when: Never — content attribution after deletion requires handling.
Detail on fail: Describe the content handling. Example: "Posts remain attributed to original user ID even after deletion. Frontend may show 'User #12345' but original identity can be traced." or "User profile deleted but comments remain visible with deleted user's name."
Remediation: Anonymize or remove content consistently:
async function deleteUserContent(userId: string) {
const anonymousUser = await db.user.findUnique({
where: { username: 'DELETED_USER' }
});
// Option 1: Remove entirely (if no context needed)
await db.post.deleteMany({ where: { authorId: userId } });
// Option 2: Anonymize (preserve context)
await db.post.updateMany({
where: { authorId: userId },
data: { authorId: anonymousUser.id }
});
// Also handle comments and other content
await db.comment.updateMany({
where: { authorId: userId },
data: { authorId: anonymousUser.id }
});
// Clean up relationships
await db.like.deleteMany({
where: { OR: [{ userId }, { postAuthorId: userId }] }
});
}