From 468be6ed514c0915f22a3bd1013af505eaff6ff8 Mon Sep 17 00:00:00 2001
From: fly_mc <me@flymc.cc>
Date: Tue, 26 Nov 2024 21:31:29 +0800
Subject: [PATCH] Filter Add / Remove activities with non-Note payloads

---
 .../backend/src/core/activitypub/ApInboxService.ts | 14 +++++++++++---
 packages/backend/src/core/activitypub/type.ts      |  1 +
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index 2f8f3ad21..3cf721366 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -31,7 +31,7 @@ import { GlobalEventService } from '@/core/GlobalEventService.js';
 import { AbuseReportService } from '@/core/AbuseReportService.js';
 import { IdentifiableError } from '@/misc/identifiable-error.js';
 import { fromTuple } from '@/misc/from-tuple.js';
-import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
+import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isApObject, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
 import { ApNoteService } from './models/ApNoteService.js';
 import { ApLoggerService } from './ApLoggerService.js';
 import { ApDbResolverService } from './ApDbResolverService.js';
@@ -273,8 +273,12 @@ export class ApInboxService {
 		}
 
 		if (activity.target === actor.featured) {
-			const object = fromTuple(activity.object);
-			const note = await this.apNoteService.resolveNote(object, { resolver });
+			const activityObject = fromTuple(activity.object);
+			if (isApObject(activityObject) && !isPost(activityObject)) {
+				return `unsupported featured object type: ${getApType(activityObject)}`;
+			}
+
+			const note = await this.apNoteService.resolveNote(activityObject, { resolver });
 			if (note == null) return 'note not found';
 			await this.notePiningService.addPinned(actor, note.id);
 			return;
@@ -638,6 +642,10 @@ export class ApInboxService {
 
 		if (activity.target === actor.featured) {
 			const activityObject = fromTuple(activity.object);
+			if (isApObject(activityObject) && !isPost(activityObject)) {
+				return `unsupported featured object type: ${getApType(activityObject)}`;
+			}
+
 			const note = await this.apNoteService.resolveNote(activityObject, { resolver });
 			if (note == null) return 'note not found';
 			await this.notePiningService.removePinned(actor, note.id);
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
index 1e72db505..6b1a82ea5 100644
--- a/packages/backend/src/core/activitypub/type.ts
+++ b/packages/backend/src/core/activitypub/type.ts
@@ -344,6 +344,7 @@ export interface IMove extends IActivity {
 	target: IObject | string;
 }
 
+export const isApObject = (object: string | IObject): object is IObject => typeof(object) === 'object';
 export const isCreate = (object: IObject): object is ICreate => getApType(object) === 'Create';
 export const isDelete = (object: IObject): object is IDelete => getApType(object) === 'Delete';
 export const isUpdate = (object: IObject): object is IUpdate => getApType(object) === 'Update';