diff options
| author | 饺子w (Yumechi) <35571479+eternal-flame-AD@users.noreply.github.com> | 2025-02-23 04:21:34 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-23 19:21:34 +0900 |
| commit | 25052164c0971497f9177f88446b110e8ca91ce2 (patch) | |
| tree | 6df09b4f006d9322706d16f650c3e40b7dd7ceba /packages/backend/src/server/ServerService.ts | |
| parent | ignore js-built (#15523) (diff) | |
| download | misskey-25052164c0971497f9177f88446b110e8ca91ce2.tar.gz misskey-25052164c0971497f9177f88446b110e8ca91ce2.tar.bz2 misskey-25052164c0971497f9177f88446b110e8ca91ce2.zip | |
Merge commit from fork
* fix(backend): Fix an issue where the origin of ActivityPub lookup response was not validated correctly.
[GHSA-6w2c-vf6f-xf26](https://github.com/misskey-dev/misskey/security/advisories/GHSA-6w2c-vf6f-xf26)
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
* Enhance: Add configuration option to disable all external redirects when responding to an ActivityPub lookup (config.disallowExternalApRedirect)
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
* fixup! fix(backend): Fix an issue where the origin of ActivityPub lookup response was not validated correctly.
* docs & one edge case
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
* apply suggestions
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
* remove stale frontend reference to _responseInvalidIdHostNotMatch
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
* apply suggestions
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
---------
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
Diffstat (limited to 'packages/backend/src/server/ServerService.ts')
| -rw-r--r-- | packages/backend/src/server/ServerService.ts | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts index fd2bd3267d..b899053287 100644 --- a/packages/backend/src/server/ServerService.ts +++ b/packages/backend/src/server/ServerService.ts @@ -103,6 +103,43 @@ export class ServerService implements OnApplicationShutdown { serve: false, }); + // if the requester looks like to be performing an ActivityPub object lookup, reject all external redirects + // + // this will break lookup that involve copying a URL from a third-party server, like trying to lookup http://charlie.example.com/@alice@alice.com + // + // this is not required by standard but protect us from peers that did not validate final URL. + if (this.config.disallowExternalApRedirect) { + const maybeApLookupRegex = /application\/activity\+json|application\/ld\+json.+activitystreams/i; + fastify.addHook('onSend', (request, reply, _, done) => { + const location = reply.getHeader('location'); + if (reply.statusCode < 300 || reply.statusCode >= 400 || typeof location !== 'string') { + done(); + return; + } + + if (!maybeApLookupRegex.test(request.headers.accept ?? '')) { + done(); + return; + } + + const effectiveLocation = process.env.NODE_ENV === 'production' ? location : location.replace(/^http:\/\//, 'https://'); + if (effectiveLocation.startsWith(`https://${this.config.host}/`)) { + done(); + return; + } + + reply.status(406); + reply.removeHeader('location'); + reply.header('content-type', 'text/plain; charset=utf-8'); + reply.header('link', `<${encodeURI(location)}>; rel="canonical"`); + done(null, [ + "Refusing to relay remote ActivityPub object lookup.", + "", + `Please remove 'application/activity+json' and 'application/ld+json' from the Accept header or fetch using the authoritative URL at ${location}.`, + ].join('\n')); + }); + } + fastify.register(this.apiServerService.createServer, { prefix: '/api' }); fastify.register(this.openApiServerService.createServer); fastify.register(this.fileServerService.createServer); |