diff --git a/packages/backend/src/core/DownloadService.ts b/packages/backend/src/core/DownloadService.ts index 8921b7e3f2..103338db79 100644 --- a/packages/backend/src/core/DownloadService.ts +++ b/packages/backend/src/core/DownloadService.ts @@ -44,6 +44,14 @@ export class DownloadService { const maxSize = this.config.maxFileSize; const urlObj = new URL(url); + if (urlObj.protocol && urlObj.protocol !== 'https:') { + throw new Error(`Unsupported protocol: ${urlObj.protocol}, only HTTPS is supported`); + } + urlObj.protocol = 'https:'; + if (urlObj.port && urlObj.port !== '443') { + throw new Error(`Unsupported port: ${urlObj.port}, only 443 is supported`); + } + let filename = urlObj.pathname.split('/').pop() ?? 'untitled'; const req = got.stream(url, { diff --git a/packages/backend/src/core/HttpRequestService.ts b/packages/backend/src/core/HttpRequestService.ts index 36f6dc3288..885c473798 100644 --- a/packages/backend/src/core/HttpRequestService.ts +++ b/packages/backend/src/core/HttpRequestService.ts @@ -171,9 +171,10 @@ export class HttpRequestService { */ @bindThis public getAgentByUrl(url: URL, bypassProxy = false): https.Agent { - if (url.protocol !== 'https:') { + if (url.protocol && url.protocol !== 'https:') { throw new Error('Invalid protocol'); } + url.protocol = 'https:'; if (url.port && url.port !== '443') { throw new Error('Invalid port'); } diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts index b4fbaf24e4..0ef7f5ad56 100644 --- a/packages/backend/src/core/activitypub/ApResolverService.ts +++ b/packages/backend/src/core/activitypub/ApResolverService.ts @@ -64,7 +64,7 @@ export class Resolver { public async resolveCollection(value: string | IObject): Promise { const collection = typeof value === 'string' ? await this.resolve(value) - : value; + : yumeNormalizeObject(value); if (isCollectionOrOrderedCollection(collection)) { return collection; @@ -74,7 +74,7 @@ export class Resolver { } @bindThis - public async resolveNotNormalized(value: string | IObject): Promise { + private async resolveNotNormalized(value: string | IObject): Promise { if (typeof value !== 'string') { return value; } diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts index 7200d04f5a..4c993a6160 100644 --- a/packages/backend/src/core/activitypub/type.ts +++ b/packages/backend/src/core/activitypub/type.ts @@ -103,26 +103,33 @@ export function yumeNormalizeRecursive 64) { throw new bull.UnrecoverableError('array length limit exceeded'); } - return object.flatMap(yumeNormalizeRecursive); + return object.flatMap((x) => yumeNormalizeRecursive(x, depth + (object.length + 3 / 4))); } - return yumeNormalizeObject(object); + return yumeNormalizeObject(object, depth + 1); } -export function yumeNormalizeObject(object: IUnsanitizedObject): IObject { +export function yumeNormalizeObject(object: IUnsanitizedObject, depth = 0): IObject { if (object.cc) { - object.cc = yumeNormalizeRecursive(object.cc); + object.cc = yumeNormalizeRecursive(object.cc, depth + 1); } if (object.id) { object.id = yumeNormalizeURL(object.id); } if (object.url) { - object.url = yumeNormalizeRecursive(object.url); + object.url = yumeNormalizeRecursive(object.url, depth + 1); + } + + if (object.replies) { + object.replies.first = object.replies.first ? + typeof object.replies.first === 'string' ? yumeNormalizeURL(object.replies.first) : yumeNormalizeObject(object.replies.first, depth + 1) : undefined; + object.replies.items = object.replies.items ? + typeof object.replies.items === 'string' ? yumeNormalizeURL(object.replies.items) : yumeNormalizeRecursive(object.replies.items, depth + 1) : undefined; } if (object.inReplyTo) { - object.inReplyTo = yumeNormalizeRecursive(object.inReplyTo); + object.inReplyTo = yumeNormalizeRecursive(object.inReplyTo, depth + 1); } return object as IObject;