mbweb is the Node.js/Express web console for Mediabot v3.
This article documents the bugs identified and fixed during
the audit of snapshot 20260427-2350.
File: app.js
fetchMetrics() existed in the codebase but was never called
from the GET / handler. data.metrics was therefore always
undefined, and the βBot Mediabot β live metricsβ section
never appeared on the homepage.
Fix: parallel call via Promise.all alongside getDashboardData().
Metric names were also aligned to the actual names exposed by the
Prometheus endpoint (mediabot_up, mediabot_current_channels,
mediabot_partyline_sessions_current, etc.).
getCommands(): SQL crash on category filterFile: lib/mediabotRepository.js
When the PUBLIC_COMMANDS_CATEGORY table is absent (catExists = false),
catJoin is empty string, but the if (category) block was still
pushing pcc.description = ? into the WHERE clause β referencing
a non-existent alias.
Fix:
// before
if (category) {
// after
if (category && catExists) {
getAllUsersWithRoles(): ORDER BY ul.level without joinFile: lib/mediabotRepository.js
ORDER BY COALESCE(ul.level, ...) unconditionally referenced the
ul alias from USER_LEVEL, even when the LEFT JOIN was not
generated (table absent or missing columns).
Fix: conditional orderBy variable:
const orderBy = joinLevel
? 'COALESCE(ul.level, u.id_user_level, 999)'
: 'COALESCE(u.id_user_level, 999)';
/api/status public endpoint leaking DB credentialsFile: routes/api.js
GET /api/status was accessible without authentication and returned
db.user, db.host, db.name via the ...data spread from
getDashboardData(). GET /health also leaked the full session
user object.
Fix:
/api/status: added requireLogin + isOwner() guard + try/catch/health: response reduced to { ok, service, timestamp }Files: lib/db.js / lib/mediabotRepository.js
db.js maintained _columnCache via tableColumns().
mediabotRepository.js maintained a separate _repoColumnCache
via getColumns() with its own TTL. Calling clearColumnCache()
from db.js left the repository cache stale.
Fix: removed _repoColumnCache and _REPO_CACHE_TTL from the
repository. getColumns() now delegates to tableColumns() from
db.js β single source of truth.
err.message leaked in login redirect URLFile: routes/auth.js
The catch block in POST /login was including err.message in
the ?error= redirect parameter, potentially exposing internal
details (MySQL message, table name, partial stack) in the URL
visible to the user.
Fix: generic user-facing message; err.message preserved in
journalctl logs only.
| # | Category | Status |
|---|---|---|
| 1 | Bug β homepage metrics | β fixed |
| 2a | Bug β SQL getCommands | β fixed |
| 2b | Bug β SQL getAllUsersWithRoles | β fixed |
| 3 | Security β public endpoints | β fixed |
| 4 | Refactor β duplicate column cache | β fixed |
| 5 | Security β err.message leak | β fixed |
Next steps: dead code in viewHelpers.js, incomplete nav
(Quotes / Commands / Network), app.js split into route files,
CSRF on login form.
You must be logged in to reply.