From b78fdb15db6dd1cfda96fece7fa6ef4136f5a212 Mon Sep 17 00:00:00 2001 From: eternal-flame-AD <yume@yumechi.jp> Date: Fri, 14 Feb 2025 06:12:49 -0600 Subject: [PATCH] Refuse all remote AP redirects Signed-off-by: eternal-flame-AD <yume@yumechi.jp> --- packages/backend/src/server/ServerService.ts | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts index 818efd8740..d1b8e9e05a 100644 --- a/packages/backend/src/server/ServerService.ts +++ b/packages/backend/src/server/ServerService.ts @@ -290,6 +290,35 @@ export class ServerService implements OnApplicationShutdown { done(); }); + fastify.addHook('onSend', (request, reply, payload, done) => { + if (reply.statusCode >= 300 && reply.statusCode < 400) { + const isAp = ["application/activity+json", "application/ld+json"].some(type => request.headers.accept?.includes(type)); + + if (isAp) { + const location = reply.getHeader('location'); + + // the only acceptable redirect is to our own domain + if (typeof location === 'string') { + // allow http in development + const normalizedLocation = process.env.NODE_ENV !== 'production' ? + location.replace(/^http:\/\//, 'https://') : location; + + if ([`https://${this.config.host}/`, `https://${this.config.hostname}/`].some(host => normalizedLocation.startsWith(host))) { + done(null, payload); + return; + } + } + + reply.code(406); + reply.removeHeader('location'); + done(null, null); + return; + } + } + + done(null, payload); + }); + // CSP if (process.env.NODE_ENV === 'production' && !this.config.browserSandboxing.csp?.disable) { console.debug('cspPrerenderedContent', this.config.cspPrerenderedContent);