fix(avatars): every signed-in account sees other users' pictures

System Health shows every user's name and avatarAt to everyone, but the
picture route GET /api/users/:id/avatar sat under the staff-only /users
prefix, so a developer got 403 EADMIN and saw only initials. authGuard now
lets any signed-in account make that one read (EVERYONE_READS); every
other /users path stays staff-only, and the test checks both.
This commit is contained in:
2026-11-02 16:40:29 +07:00
parent 3ec1978176
commit 600e8eec6a
6 changed files with 22 additions and 11 deletions
+6
View File
@@ -128,6 +128,11 @@ const STAFF_ONLY_PREFIXES = [
// Staff-only paths with an id in the middle, matched on `apiPath()`'s
// lower-cased form: the host's own AI-tool config files (they may hold keys).
const STAFF_ONLY_PATTERNS = [/^\/ai-tools\/[^/]+\/config(\/|$)/];
// The one read under a staff-only prefix every signed-in user may make: an
// account's PICTURE (`GET /users/:id/avatar` — the image or a redirect to its
// link, nothing else of the account). System Health shows every user's name and
// `avatarAt` to everyone, so a developer refused here saw only initials.
const EVERYONE_READS = [/^\/users\/\d+\/avatar$/];
const isServerMode = () => process.env.AGENTHUB_MODE === "server";
@@ -789,6 +794,7 @@ function authGuard(req, res, next) {
const isRead = req.method === "GET" || req.method === "HEAD";
if (
user.role === "developer" &&
!(isRead && EVERYONE_READS.some((re) => re.test(lp))) &&
(STAFF_ONLY_PREFIXES.some(under) || STAFF_ONLY_PATTERNS.some((re) => re.test(lp)))
) {
return deny(res, 403, "EADMIN", "only an admin or analyst may open this");