From 3a81f9032201adfe355a1aa35cdf59bb67172f93 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 6 Nov 2025 15:51:23 -0500 Subject: [PATCH 1/3] fix: make i18n test failure message easier to read --- test/i18n.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/i18n.js b/test/i18n.js index 5798f3d12f..f2abe4f17a 100644 --- a/test/i18n.js +++ b/test/i18n.js @@ -163,7 +163,7 @@ describe('i18n', () => { assert.strictEqual( sourceKeys.length, translationKeys.length, - `Extra keys found in namespace ${namespace.slice(1, -5)} for language "${language}"` + `Extra keys found in namespace "${namespace.slice(1, -5)}" for language "${language}"` ); }); }); From 5d9da6035e3aa74c0e95f7c16d36c18deb690999 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 10 Nov 2025 11:55:19 -0500 Subject: [PATCH 2/3] fix: log out user if session cookie resolves to non-existent uid --- src/controllers/authentication.js | 2 +- src/middleware/user.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/controllers/authentication.js b/src/controllers/authentication.js index 581f7d931c..162bea8ecd 100644 --- a/src/controllers/authentication.js +++ b/src/controllers/authentication.js @@ -490,7 +490,7 @@ authenticationController.logout = async function (req, res) { }; await plugins.hooks.fire('filter:user.logout', payload); - if (req.body?.noscript === 'true') { + if (req.body?.noscript === 'true' || res.locals.logoutRedirect === true) { return res.redirect(payload.next); } res.status(200).send(payload); diff --git a/src/middleware/user.js b/src/middleware/user.js index c49481e625..620c4bad9c 100644 --- a/src/middleware/user.js +++ b/src/middleware/user.js @@ -53,6 +53,12 @@ module.exports = function (middleware) { } if (req.loggedIn) { + const exists = await user.exists(req.uid); + if (!exists) { + res.locals.logoutRedirect = true; + return controllers.authentication.logout(req, res); + } + return true; } else if (req.headers.hasOwnProperty('authorization')) { const user = await passportAuthenticateAsync(req, res); From 9900171f24f26fa6d88237d109ce401926616843 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Thu, 13 Nov 2025 12:25:16 -0500 Subject: [PATCH 3/3] fix: crash in resolveInboxes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2025-11-13T12:38:44.161Z [4568/2508892] - error: uncaughtException: Invalid URL TypeError: Invalid URL at new URL (node:internal/url:818:25) at /home/saas/nodebb/src/activitypub/index.js:123:25 at Array.filter () at ActivityPub.resolveInboxes (/home/saas/nodebb/src/activitypub/index.js:122:13) at ActivityPub.send (/home/saas/nodebb/src/activitypub/index.js:424:36) at Object.announce (/home/saas/nodebb/src/activitypub/feps.js:72:20) --- src/activitypub/index.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/activitypub/index.js b/src/activitypub/index.js index 5971c69326..e64dd66d6b 100644 --- a/src/activitypub/index.js +++ b/src/activitypub/index.js @@ -119,8 +119,13 @@ ActivityPub.resolveInboxes = async (ids) => { if (!meta.config.activitypubAllowLoopback) { ids = ids.filter((id) => { - const { hostname } = new URL(id); - return hostname !== nconf.get('url_parsed').hostname; + try { + const { hostname } = new URL(id); + return hostname !== nconf.get('url_parsed').hostname; + } catch (err) { + winston.error(`[activitypub/resolveInboxes] Invalid id: ${id}`); + return false; + } }); }