Add notActivityPub middleware to stop AP requests on /users/*

This commit is contained in:
Alex Gleason 2025-01-21 18:34:34 -06:00
parent 3fd311b929
commit 281872b0ad
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
3 changed files with 20 additions and 21 deletions

View file

@ -133,6 +133,7 @@ import { DittoTranslator } from '@/interfaces/DittoTranslator.ts';
import { auth98Middleware, requireProof, requireRole } from '@/middleware/auth98Middleware.ts'; import { auth98Middleware, requireProof, requireRole } from '@/middleware/auth98Middleware.ts';
import { cspMiddleware } from '@/middleware/cspMiddleware.ts'; import { cspMiddleware } from '@/middleware/cspMiddleware.ts';
import { metricsMiddleware } from '@/middleware/metricsMiddleware.ts'; import { metricsMiddleware } from '@/middleware/metricsMiddleware.ts';
import { notActivitypubMiddleware } from '@/middleware/notActivitypubMiddleware.ts';
import { paginationMiddleware } from '@/middleware/paginationMiddleware.ts'; import { paginationMiddleware } from '@/middleware/paginationMiddleware.ts';
import { rateLimitMiddleware } from '@/middleware/rateLimitMiddleware.ts'; import { rateLimitMiddleware } from '@/middleware/rateLimitMiddleware.ts';
import { requireSigner } from '@/middleware/requireSigner.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('/api/*', metricsMiddleware, paginationMiddleware, logger(debug));
app.use('/.well-known/*', metricsMiddleware, logger(debug)); app.use('/.well-known/*', metricsMiddleware, logger(debug));
app.use('/users/*', metricsMiddleware, logger(debug));
app.use('/nodeinfo/*', metricsMiddleware, logger(debug)); app.use('/nodeinfo/*', metricsMiddleware, logger(debug));
app.use('/oauth/*', 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('/:acct{@.*}/*', frontendController); app.get('/:acct{@.*}/*', frontendController);
app.get('/:bech32{^[\x21-\x7E]{1,83}1[023456789acdefghjklmnpqrstuvwxyz]{6,}$}', 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('/tags/*', frontendController);
app.get('/statuses/*', frontendController); app.get('/statuses/*', frontendController);
app.get('/notice/*', frontendController); app.get('/notice/*', frontendController);

View file

@ -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();
};

View file

@ -261,24 +261,6 @@ function paginatedList(
return c.json(results, 200, headers); return c.json(results, 200, headers);
} }
/** JSON-LD context. */
type LDContext = (string | Record<string, string | Record<string, string>>)[];
/** Add a basic JSON-LD context to ActivityStreams object, if it doesn't already exist. */
function maybeAddContext<T>(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<T, P extends string>(c: Context<any, P>, 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. */ /** Rewrite the URL of the request object to use the local domain. */
function localRequest(c: Context): Request { function localRequest(c: Context): Request {
return Object.create(c.req.raw, { return Object.create(c.req.raw, {
@ -300,7 +282,6 @@ function assertAuthenticated(c: AppContext, author: NostrEvent): void {
} }
export { export {
activityJson,
assertAuthenticated, assertAuthenticated,
createAdminEvent, createAdminEvent,
createEvent, createEvent,