Activity status — 'last seen 3 minutes ago', 'currently online', 'typing' — reveals real-time behavioral patterns that users may want to keep private for safety or personal reasons. Domestic abuse victims, people avoiding specific contacts, and users who want to read messages without triggering social pressure are all impacted by forced activity disclosure. GDPR Art. 25 (privacy by design) requires that data minimization be the default: broadcast activity only when users have affirmatively chosen to share it. CWE-200 captures the information exposure when status fields are included in API responses regardless of user preference.
Low because the exposed data is behavioral metadata rather than account credentials or PII, but the real-time nature makes it a safety concern for vulnerable users.
Check the activityStatusVisible setting before including any lastSeen, isOnline, or typing indicators in API responses or WebSocket broadcasts. Apply the check server-side — omitting the field from the response is more reliable than frontend suppression. In your user profile serializer:
// src/lib/users/serialize.ts
export async function serializeUser(user: User, viewerId: string): Promise<PublicUser> {
const settings = await db.userSettings.findUnique({ where: { userId: user.id } });
return {
id: user.id,
name: user.name,
// conditionally include activity
...(settings?.activityStatusVisible && {
lastSeen: user.lastSeen,
isOnline: isUserOnline(user.id)
})
};
}
Also gate the WebSocket presence broadcast: skip emitting user:online and user:typing events for users with activity status disabled.
ID: community-privacy-controls.account-control.activity-status-toggle
Severity: low
What to look for: Enumerate every relevant item. Check whether the platform shows "last seen", "currently active", "typing", or similar activity status. Look for a settings toggle to hide this status. Verify that when disabled, the status is not revealed in API responses or via WebSocket events.
Pass criteria: At least 1 of the following conditions is met. Settings include a toggle to disable activity status sharing. When disabled, last_seen, isOnline, or similar fields are omitted from API responses. Activity is not broadcast via real-time channels.
Fail criteria: Activity status always visible to other users. No setting to disable. Status is sent via API even if user has disabled it.
Skip (N/A) when: The platform does not display activity status.
Detail on fail: Example: "Activity status always visible in API responses regardless of user setting."
Remediation: Implement activity status privacy:
// In user profile response
async function getUserProfile(userId: string, viewerId: string) {
const user = await db.user.findUnique({ where: { id: userId } });
const settings = await db.userSettings.findUnique({ where: { userId } });
const profile = {
id: user.id,
name: user.name,
// ... other fields
};
// Only include activity if user allows it
if (settings?.activityStatusVisible) {
profile.lastSeen = user.lastSeen;
profile.isOnline = isUserOnline(userId);
}
return profile;
}