From ae5d2d40d718dbab04d88a6de07bbed3229c5e2c Mon Sep 17 00:00:00 2001 From: "SASAPIYO (SASAGAWA Kiyoshi)" Date: Fri, 19 Jun 2026 15:00:17 +0900 Subject: [PATCH] fix(backend): skip inbox activities without an actor instead of throwing TypeError (#17558) * fix(backend): skip inbox activities without an actor instead of throwing TypeError - guard getApId() against null/undefined (and fix the 'detemine' typo) - skip actor-less inbox activities early with Bull.UnrecoverableError Fixes #17557 * fix(backend): reject actor-less inbox activities at enqueue time Per review feedback (#17558), move the actor presence check to the inbox HTTP handler and drop the processor-side guard. - ActivityPubServerService.inbox(): validate the request body from the loose (unknown) type and return 400 for structurally invalid activities (non-object / missing actor) instead of enqueueing a job that can never be authenticated. Avoids useless retries and TypeError noise. - InboxProcessorService.process(): remove the actor null guard; IActivity.actor is non-null, so the check is unnecessary once enqueue is validated. - getApId(): widen the parameter to include undefined so the existing null guard is type-honest (getOneApId can pass value[0] of an empty array). Co-Authored-By: Claude Opus 4.8 (1M context) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 1 + packages/backend/src/core/activitypub/type.ts | 6 +++--- .../backend/src/server/ActivityPubServerService.ts | 12 +++++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df9f79565e..eceb8edbf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ - Fix: PerUserDriveChart がシステム所有ファイル (userId が null) の更新で `"group"` の非NULL制約違反によりクラッシュする問題を修正 (#17498) - Fix: センシティブメディア自動検出周りの依存関係・ファイルの解決に失敗する問題を修正 - Fix: フォロワー限定投稿を指名投稿で引用した際に、引用した投稿の公開範囲が意図せず変更される問題を修正 +- Fix: `actor` を持たない不正なInboxアクティビティを受信した際に配送ジョブが `TypeError` でクラッシュする問題を修正 (受信時に検証して400で返し、ジョブを積まないように変更) - Fix: Startup and shutdown failures (port-in-use, socket permission denied, plugin timeouts, leaked WebSocket connections) are now reported through the misskey logger instead of an UnhandledPromiseRejectionWarning stack trace - Fix: リモートのノートに対するメンション数制限が、サーバーが解決できたユーザー数ベースで行われていた問題を修正 diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts index fd76a3d9fa..99668813a4 100644 --- a/packages/backend/src/core/activitypub/type.ts +++ b/packages/backend/src/core/activitypub/type.ts @@ -58,10 +58,10 @@ export function getOneApId(value: ApObject): string { /** * Get ActivityStreams Object id */ -export function getApId(value: string | IObject): string { +export function getApId(value: string | IObject | undefined): string { if (typeof value === 'string') return value; - if (typeof value.id === 'string') return value.id; - throw new Error('cannot detemine id'); + if (value != null && typeof value.id === 'string') return value.id; + throw new Error('cannot determine id'); } /** diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts index cbbeb78f68..5dbdf4014b 100644 --- a/packages/backend/src/server/ActivityPubServerService.ts +++ b/packages/backend/src/server/ActivityPubServerService.ts @@ -174,7 +174,17 @@ export class ActivityPubServerService { } } - this.queueService.inbox(request.body as IActivity, signature); + const body = request.body; + + // Reject structurally invalid activities (e.g. missing actor) here instead + // of letting them fail deep inside the inbox processor. An actor-less + // activity can never be authenticated, so there is no point enqueueing it. + if (typeof body !== 'object' || body == null || !('actor' in body) || body.actor == null) { + reply.code(400); + return; + } + + this.queueService.inbox(body as IActivity, signature); reply.code(202); }