User bans and suspensions are enforced
Why it matters
Without enforceable bans, repeat violators face no real consequence — they continue posting after receiving warnings, and the moderation system becomes a signal they can ignore. OWASP A01:2021 (Broken Access Control, CWE-285) applies when ban records exist in the database but the enforcement check is missing from content-creation and interaction endpoints. A ban table with no WHERE clause enforcement is a paper ban: the record exists, but the behavior continues. Communities with no ban enforcement experience higher recidivism from bad actors who quickly learn there is no real cost to violations.
Severity rationale
High because without enforcement checks at content-creation endpoints, banned users can immediately resume posting, rendering all prior moderation actions ineffective.
Remediation
Check ban status at the start of every content-creation and interaction handler. Invalidate sessions on ban to force immediate logout:
async function assertNotBanned(userId) {
const user = await db.users.findOneById(userId);
if (!user.banned) return;
// Auto-lift expired temporary bans
if (user.bannedUntil && user.bannedUntil < new Date()) {
await db.users.update(userId, { banned: false, bannedUntil: null });
return;
}
throw Object.assign(new Error('Account is banned'), { status: 403 });
}
// Apply at every post/comment/message endpoint
app.post('/api/posts', authenticate, async (req, res) => {
await assertNotBanned(req.user.id);
// ... create post
});
Store bans with at minimum: userId, reason, bannedAt, bannedBy, and optional bannedUntil for temporary suspensions.
Detection
-
ID:
user-bans -
Severity:
high -
What to look for: Check if moderators can ban or suspend users. Look for a user ban/suspension table or feature. Verify that banned users cannot post, comment, or create new accounts (or face friction).
-
Pass criteria: Moderators can ban/suspend users for policy violations through at least 1 explicit mechanism (admin UI, CLI, or API endpoint). Enumerate all content-creation and interaction endpoints and confirm each checks the ban status before allowing action. Banned users cannot post new content or interact with the platform. A ban record is maintained with at least 3 fields: user ID, reason, and timestamp.
-
Fail criteria: No user ban mechanism exists, or banned users can still post by creating new accounts. A ban table with no enforcement check in the post-creation path does not count as pass.
-
Skip (N/A) when: Never — enforcement against repeat violators is essential.
-
Detail on fail:
"No ban mechanism exists. Abusive users cannot be removed from the platform." -
Remediation: Implement user bans that prevent banned users from posting or interacting:
// Moderator endpoint to ban user app.patch('/api/admin/users/:id/ban', verifyModerator, async (req, res) => { const { reason, duration } = req.body; // Calculate ban expiration (null = permanent) const bannedUntil = duration ? new Date(Date.now() + duration) : null; // Update user record await db.users.updateOne( { _id: req.params.id }, { banned: true, bannedReason: reason, bannedUntil, bannedAt: new Date(), bannedBy: req.user.id } ); // Invalidate all active sessions to force logout await db.sessions.deleteMany({ userId: req.params.id }); res.status(200).json({ success: true, message: 'User banned' }); }); // Check ban status before all actions async function checkUserBan(userId) { const user = await db.users.findOne({ _id: userId }); if (user.banned) { // Check if ban is temporary and expired if (user.bannedUntil && user.bannedUntil < new Date()) { // Unban user automatically await db.users.updateOne( { _id: userId }, { banned: false, bannedUntil: null } ); } else { throw new Error('User is banned'); } } } // Middleware to enforce ban check on posting app.post('/api/posts', authenticate, async (req, res) => { try { await checkUserBan(req.user.id); } catch (err) { return res.status(403).json({ error: err.message }); } // ... create post });
External references
- cwe · CWE-285 — Improper Authorization
- owasp:2021 · A01 — Broken Access Control
Taxons
History
- 2026-04-18·v1.0.0·Initial import from community-moderation-safety·automated