[Security][High] No role-based authorization — editor role is never enforced #10

Closed
opened 2026-07-02 01:20:44 +00:00 by wtclaude · 0 comments
Member

Severity: High · Type: Security / access control

Problem

isLoggedIn (server/src/utils/auth.js:81) only verifies that the JWT is valid. Every admin route is gated by isLoggedIn alone (server/src/router/v1/admin/admin.routes.js:15). The system defines two roles (admin, editor), but no route ever checks req.user.role — the only role logic is two narrow "last admin" guards in admin.controller.js.

Impact

A low-privilege editor can call any admin endpoint:

  • POST /admin/users — create a new admin
  • PUT /admin/users/:id — promote themselves to admin
  • DELETE /admin/users/:id — delete other users
  • PUT /admin/site-mode — flip the site in/out of maintenance
  • delete any wiki page, etc.

This is a privilege-escalation hole: any authenticated non-admin effectively has full admin power.

Suggested fix

Add a role-gate middleware and apply it to admin-only routes (/users/*, /site-mode, and anything else that should be admin-only):

function requireRole(...roles) {
  return (req, res, next) =>
    roles.includes(req.user?.role) ? next() : res.status(403).json({ message: 'Forbidden' })
}

Decide per-route which operations editor may perform (likely content: posts/wiki) vs. admin-only (users, site mode, settings).

**Severity:** High · **Type:** Security / access control ## Problem `isLoggedIn` (`server/src/utils/auth.js:81`) only verifies that the JWT is valid. Every admin route is gated by `isLoggedIn` alone (`server/src/router/v1/admin/admin.routes.js:15`). The system defines two roles (`admin`, `editor`), but **no route ever checks `req.user.role`** — the only role logic is two narrow "last admin" guards in `admin.controller.js`. ## Impact A low-privilege `editor` can call any admin endpoint: - `POST /admin/users` — create a new admin - `PUT /admin/users/:id` — promote themselves to admin - `DELETE /admin/users/:id` — delete other users - `PUT /admin/site-mode` — flip the site in/out of maintenance - delete any wiki page, etc. This is a privilege-escalation hole: any authenticated non-admin effectively has full admin power. ## Suggested fix Add a role-gate middleware and apply it to admin-only routes (`/users/*`, `/site-mode`, and anything else that should be admin-only): ```js function requireRole(...roles) { return (req, res, next) => roles.includes(req.user?.role) ? next() : res.status(403).json({ message: 'Forbidden' }) } ``` Decide per-route which operations `editor` may perform (likely content: posts/wiki) vs. admin-only (users, site mode, settings).
Sign in to join this conversation.
No description provided.