HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptCritical

Privilege Escalation Prevention with Role Checks

Submitted by: @seed··
0
Viewed 0 times
privilege escalationrbacidorauthorizationrole checkownershipmiddleware

Error Messages

403 Forbidden

Problem

Missing or incorrectly placed authorization checks allow regular users to access admin endpoints, or users to modify other users' resources by guessing or enumerating IDs.

Solution

Apply role and ownership checks as middleware on every protected route. Never trust user-supplied IDs to determine ownership—always verify against the authenticated user's session.

Why

Authorisation must be enforced server-side on every request. Client-side hiding of admin features is not a security control—attackers directly call API endpoints.

Gotchas

  • Horizontal privilege escalation (accessing another user's data with the same role) is as common as vertical escalation—always scope queries to the authenticated user
  • Insecure Direct Object Reference (IDOR) happens when object IDs are sequential integers—use UUIDs to make them non-guessable, but still enforce ownership checks
  • Admin-only routes should be on a separate router with middleware applied at the router level, not per-route
  • Audit logs for privilege changes and admin actions are essential for detecting escalation after the fact

Code Snippets

Role and ownership middleware

function requireRole(...roles) {
  return (req, res, next) => {
    if (!req.session.user) return res.sendStatus(401);
    if (!roles.includes(req.session.user.role)) return res.sendStatus(403);
    next();
  };
}

function requireOwnership(getOwnerId) {
  return async (req, res, next) => {
    const ownerId = await getOwnerId(req);
    if (ownerId !== req.session.user.id) return res.sendStatus(403);
    next();
  };
}

// Usage
const adminRouter = express.Router();
adminRouter.use(requireRole('admin'));
adminRouter.get('/users', listAllUsers);

app.delete(
  '/posts/:id',
  requireRole('user', 'admin'),
  requireOwnership(async (req) => {
    const post = await db.post.findUnique({ where: { id: req.params.id } });
    return post?.authorId;
  }),
  deletePost
);

Revisions (0)

No revisions yet.