From e70e990a1aa932a3f994b2205bacc2f35730aa01 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 22 May 2025 14:13:41 -0400 Subject: [PATCH 1/4] feat: restrict access to ap.probe method to registered users, add rate limiting protection --- src/activitypub/index.js | 22 ++++++++++++++++++++++ src/controllers/activitypub/index.js | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/activitypub/index.js b/src/activitypub/index.js index c87a0654f3..4067405080 100644 --- a/src/activitypub/index.js +++ b/src/activitypub/index.js @@ -27,6 +27,9 @@ const probeCache = ttl({ max: 500, ttl: 1000 * 60 * 60, // 1 hour }); +const probeRateLimit = ttl({ + ttl: 1000 * 3, // 3 seconds +}); const ActivityPub = module.exports; @@ -506,6 +509,13 @@ ActivityPub.probe = async ({ uid, url }) => { * - Returns a relative path if already available, true if not, and false otherwise. */ + // Disable on config setting; restrict lookups to HTTPS-enabled URLs only + const { activitypubProbe } = meta.config; + const { protocol } = new URL(url); + if (!activitypubProbe || protocol !== 'https:') { + return false; + } + // Known resources const [isNote, isMessage, isActor, isActorUrl] = await Promise.all([ posts.exists(url), @@ -541,6 +551,17 @@ ActivityPub.probe = async ({ uid, url }) => { } } + // Guests not allowed to use expensive logic path + if (!uid) { + return false; + } + + // One request allowed every 3 seconds (configured at top) + const limited = probeRateLimit.get(uid); + if (limited) { + return false; + } + // Cached result if (probeCache.has(url)) { return probeCache.get(url); @@ -572,6 +593,7 @@ ActivityPub.probe = async ({ uid, url }) => { return false; } try { + probeRateLimit.set(uid, true); return await checkHeader(meta.config.activitypubProbeTimeout || 2000); } catch (e) { if (e.name === 'TimeoutError') { diff --git a/src/controllers/activitypub/index.js b/src/controllers/activitypub/index.js index 36054d6616..0e7112ddfd 100644 --- a/src/controllers/activitypub/index.js +++ b/src/controllers/activitypub/index.js @@ -31,7 +31,7 @@ Controller.fetch = async (req, res, next) => { if (typeof result === 'string') { return helpers.redirect(res, result); } else if (result) { - const { id, type } = await activitypub.get('uid', req.uid || 0, url.href); + const { id, type } = await activitypub.get('uid', req.uid, url.href); switch (true) { case activitypub._constants.acceptedPostTypes.includes(type): { return helpers.redirect(res, `/post/${encodeURIComponent(id)}`); From 30aa0fe6d25c0b5aac9df422818911e909c178aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sat, 24 May 2025 11:49:49 -0400 Subject: [PATCH 2/4] chore: up dbsearch --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index 331013f700..b47fba2015 100644 --- a/install/package.json +++ b/install/package.json @@ -99,7 +99,7 @@ "nconf": "0.13.0", "nodebb-plugin-2factor": "7.5.10", "nodebb-plugin-composer-default": "10.2.50", - "nodebb-plugin-dbsearch": "6.2.16", + "nodebb-plugin-dbsearch": "6.2.18", "nodebb-plugin-emoji": "6.0.2", "nodebb-plugin-emoji-android": "4.1.1", "nodebb-plugin-markdown": "13.2.1", From e2de0ec212bda29ae419f81fc92cad122da99e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sat, 24 May 2025 16:50:53 -0400 Subject: [PATCH 3/4] chore: up dbsearch --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index b47fba2015..c8298570fd 100644 --- a/install/package.json +++ b/install/package.json @@ -99,7 +99,7 @@ "nconf": "0.13.0", "nodebb-plugin-2factor": "7.5.10", "nodebb-plugin-composer-default": "10.2.50", - "nodebb-plugin-dbsearch": "6.2.18", + "nodebb-plugin-dbsearch": "6.2.19", "nodebb-plugin-emoji": "6.0.2", "nodebb-plugin-emoji-android": "4.1.1", "nodebb-plugin-markdown": "13.2.1", From fd2ae7261e0e8378c10e7b8863c368ce864d5edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sun, 25 May 2025 19:04:01 -0400 Subject: [PATCH 4/4] chore: up eslint stylistic --- install/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install/package.json b/install/package.json index c8298570fd..29c2898f4f 100644 --- a/install/package.json +++ b/install/package.json @@ -162,8 +162,8 @@ "@commitlint/config-angular": "19.8.1", "coveralls": "3.1.1", "@eslint/js": "9.26.0", - "@stylistic/eslint-plugin-js": "4.2.0", - "eslint-config-nodebb": "1.1.4", + "@stylistic/eslint-plugin-js": "4.4.0", + "eslint-config-nodebb": "1.1.5", "eslint-plugin-import": "2.31.0", "grunt": "1.6.1", "grunt-contrib-watch": "1.1.0",