From 281872b0ad951afba57d5ca0582c8c4c882bb769 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 21 Jan 2025 18:34:34 -0600 Subject: [PATCH] Add notActivityPub middleware to stop AP requests on /users/* --- src/app.ts | 4 ++-- src/middleware/notActivitypubMiddleware.ts | 18 ++++++++++++++++++ src/utils/api.ts | 19 ------------------- 3 files changed, 20 insertions(+), 21 deletions(-) create mode 100644 src/middleware/notActivitypubMiddleware.ts diff --git a/src/app.ts b/src/app.ts index 32061184..b18ba281 100644 --- a/src/app.ts +++ b/src/app.ts @@ -133,6 +133,7 @@ import { DittoTranslator } from '@/interfaces/DittoTranslator.ts'; import { auth98Middleware, requireProof, requireRole } from '@/middleware/auth98Middleware.ts'; import { cspMiddleware } from '@/middleware/cspMiddleware.ts'; import { metricsMiddleware } from '@/middleware/metricsMiddleware.ts'; +import { notActivitypubMiddleware } from '@/middleware/notActivitypubMiddleware.ts'; import { paginationMiddleware } from '@/middleware/paginationMiddleware.ts'; import { rateLimitMiddleware } from '@/middleware/rateLimitMiddleware.ts'; import { requireSigner } from '@/middleware/requireSigner.ts'; @@ -179,7 +180,6 @@ app.use('*', rateLimitMiddleware(300, Time.minutes(5))); app.use('/api/*', metricsMiddleware, paginationMiddleware, logger(debug)); app.use('/.well-known/*', metricsMiddleware, logger(debug)); -app.use('/users/*', metricsMiddleware, logger(debug)); app.use('/nodeinfo/*', metricsMiddleware, logger(debug)); app.use('/oauth/*', metricsMiddleware, logger(debug)); @@ -400,7 +400,7 @@ app.use('/oauth/*', notImplementedController); app.get('/:acct{@.*}', frontendController); app.get('/:acct{@.*}/*', frontendController); app.get('/:bech32{^[\x21-\x7E]{1,83}1[023456789acdefghjklmnpqrstuvwxyz]{6,}$}', frontendController); -app.get('/users/*', frontendController); +app.get('/users/*', notActivitypubMiddleware, frontendController); app.get('/tags/*', frontendController); app.get('/statuses/*', frontendController); app.get('/notice/*', frontendController); diff --git a/src/middleware/notActivitypubMiddleware.ts b/src/middleware/notActivitypubMiddleware.ts new file mode 100644 index 00000000..b25e6f61 --- /dev/null +++ b/src/middleware/notActivitypubMiddleware.ts @@ -0,0 +1,18 @@ +import { MiddlewareHandler } from '@hono/hono'; + +const ACTIVITYPUB_TYPES = [ + 'application/activity+json', + 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', +]; + +/** Return 4xx errors on common (unsupported) ActivityPub routes to prevent AP traffic. */ +export const notActivitypubMiddleware: MiddlewareHandler = async (c, next) => { + const accept = c.req.header('accept'); + const types = accept?.split(',')?.map((type) => type.trim()) ?? []; + + if (types.every((type) => ACTIVITYPUB_TYPES.includes(type))) { + return c.text('ActivityPub is not supported', 406); + } + + await next(); +}; diff --git a/src/utils/api.ts b/src/utils/api.ts index 37cbbbf9..9e7125c6 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -261,24 +261,6 @@ function paginatedList( return c.json(results, 200, headers); } -/** JSON-LD context. */ -type LDContext = (string | Record>)[]; - -/** Add a basic JSON-LD context to ActivityStreams object, if it doesn't already exist. */ -function maybeAddContext(object: T): T & { '@context': LDContext } { - return { - '@context': ['https://www.w3.org/ns/activitystreams'], - ...object, - }; -} - -/** Like hono's `c.json()` except returns JSON-LD. */ -function activityJson(c: Context, object: T) { - const response = c.json(maybeAddContext(object)); - response.headers.set('content-type', 'application/activity+json; charset=UTF-8'); - return response; -} - /** Rewrite the URL of the request object to use the local domain. */ function localRequest(c: Context): Request { return Object.create(c.req.raw, { @@ -300,7 +282,6 @@ function assertAuthenticated(c: AppContext, author: NostrEvent): void { } export { - activityJson, assertAuthenticated, createAdminEvent, createEvent,