Platforms without block and mute features leave users with no way to protect themselves from targeted harassment. CWE-285 (Improper Authorization) applies when there is no mechanism preventing a specific user from contacting or interacting with another. COPPA 16 CFR 312.4 requires that platforms collecting data from minors provide parental control mechanisms — blocking is the foundational user-level control. Without blocking, a single bad actor can repeatedly mention, message, or comment on a victim's content with no platform-enforced boundary, and moderators cannot act fast enough to prevent sustained harassment campaigns.
High because the absence of blocking forces victims to leave the platform to escape targeted harassment — there is no in-product option for self-protection.
Implement a blocks table and enforce it across all interaction paths: messaging, commenting, and mentions. Every interaction endpoint must check block status before allowing the action:
async function assertNotBlocked(actorId: string, targetId: string) {
const block = await db.blocks.findFirst({
where: {
OR: [
{ blockerId: targetId, blockedId: actorId },
{ blockerId: actorId, blockedId: targetId },
],
},
});
if (block) throw Object.assign(new Error('Blocked'), { status: 403 });
}
A block that prevents messaging but not commenting or mentioning does not satisfy this check — every interaction path must respect the block.
ID: community-moderation-safety.policy-transparency.user-controls
Severity: high
What to look for: Check if users can block, mute, or report other users. Look for block lists, mute functionality, or private messaging controls. Verify that blocked users cannot contact the blocker.
Pass criteria: Users can block/mute other users via at least 1 explicit UI action. Blocked users cannot interact (no messages, mentions, or visibility). Users can view their block list. Enumerate all interaction paths (messaging, commenting, mentioning) and confirm each respects the block.
Fail criteria: No block/mute functionality. Users cannot protect themselves from harassment. A block that prevents messaging but not commenting or mentioning does not count as pass.
Skip (N/A) when: Never — user controls are essential.
Detail on fail: "No block feature. Users have no way to stop harassment from specific users."
Remediation: Implement blocking/muting features so users can protect themselves from harassment:
// User blocks another user
app.post('/api/users/:id/block', authenticate, async (req, res) => {
const blockerId = req.user.id;
const blockedId = req.params.id;
if (blockerId === blockedId) {
return res.status(400).json({ error: 'Cannot block yourself' });
}
await db.blocks.create({
blockerId,
blockedId,
createdAt: new Date()
});
res.status(201).json({ success: true });
});
// Get user's block list
app.get('/api/users/me/blocks', authenticate, async (req, res) => {
const blocks = await db.blocks.find({ blockerId: req.user.id });
const blockedUsers = await db.users.find({
_id: { $in: blocks.map(b => b.blockedId) }
});
res.json(blockedUsers.map(u => ({ id: u.id, name: u.name })));
});
// Check if user is blocked before fetching content
async function canUserSeeContent(viewerId, contentAuthorId) {
const isBlocked = await db.blocks.findOne({
blockerId: viewerId,
blockedId: contentAuthorId
});
return !isBlocked;
}
// Prevent blocked users from messaging each other
app.post('/api/messages', authenticate, async (req, res) => {
const { recipientId, content } = req.body;
const senderId = req.user.id;
// Check if sender is blocked by recipient
const isBlocked = await db.blocks.findOne({
blockerId: recipientId,
blockedId: senderId
});
if (isBlocked) {
return res.status(403).json({ error: 'User has blocked you' });
}
// Create message
await db.messages.create({
senderId,
recipientId,
content,
createdAt: new Date()
});
res.status(201).json({ success: true });
});