From edfded7fb7e55a83b21256469fd3a58dec1bfe20 Mon Sep 17 00:00:00 2001
From: Johann150 <johann.galle@protonmail.com>
Date: Thu, 19 May 2022 13:40:16 +0200
Subject: [PATCH] fix(activitypub): add authorization checks (#8534)

* fix spelling

* fix(activitypub): add authorization checks
---
 .../activitypub/kernel/announce/note.ts       |  3 +++
 .../remote/activitypub/kernel/delete/index.ts | 22 +++++++++----------
 .../activitypub/kernel/undo/announce.ts       |  1 +
 .../src/services/note/reaction/create.ts      |  5 +++++
 4 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/packages/backend/src/remote/activitypub/kernel/announce/note.ts b/packages/backend/src/remote/activitypub/kernel/announce/note.ts
index 680749f4d8..052751c654 100644
--- a/packages/backend/src/remote/activitypub/kernel/announce/note.ts
+++ b/packages/backend/src/remote/activitypub/kernel/announce/note.ts
@@ -9,6 +9,7 @@ import { fetchMeta } from '@/misc/fetch-meta.js';
 import { getApLock } from '@/misc/app-lock.js';
 import { parseAudience } from '../../audience.js';
 import { StatusError } from '@/misc/fetch.js';
+import { Notes } from '@/models/index.js';
 
 const logger = apLogger;
 
@@ -52,6 +53,8 @@ export default async function(resolver: Resolver, actor: CacheableRemoteUser, ac
 			throw e;
 		}
 
+		if (!await Notes.isVisibleForMe(renote, actor)) return 'skip: invalid actor for this activity';
+
 		logger.info(`Creating the (Re)Note: ${uri}`);
 
 		const activityAudience = await parseAudience(actor, activity.to, activity.cc);
diff --git a/packages/backend/src/remote/activitypub/kernel/delete/index.ts b/packages/backend/src/remote/activitypub/kernel/delete/index.ts
index 4c06a9de0b..c7064f553b 100644
--- a/packages/backend/src/remote/activitypub/kernel/delete/index.ts
+++ b/packages/backend/src/remote/activitypub/kernel/delete/index.ts
@@ -13,37 +13,37 @@ export default async (actor: CacheableRemoteUser, activity: IDelete): Promise<st
 	}
 
 	// 削除対象objectのtype
-	let formarType: string | undefined;
+	let formerType: string | undefined;
 
 	if (typeof activity.object === 'string') {
 		// typeが不明だけど、どうせ消えてるのでremote resolveしない
-		formarType = undefined;
+		formerType = undefined;
 	} else {
 		const object = activity.object as IObject;
 		if (isTombstone(object)) {
-			formarType = toSingle(object.formerType);
+			formerType = toSingle(object.formerType);
 		} else {
-			formarType = toSingle(object.type);
+			formerType = toSingle(object.type);
 		}
 	}
 
 	const uri = getApId(activity.object);
 
 	// type不明でもactorとobjectが同じならばそれはPersonに違いない
-	if (!formarType && actor.uri === uri) {
-		formarType = 'Person';
+	if (!formerType && actor.uri === uri) {
+		formerType = 'Person';
 	}
 
 	// それでもなかったらおそらくNote
-	if (!formarType) {
-		formarType = 'Note';
+	if (!formerType) {
+		formerType = 'Note';
 	}
 
-	if (validPost.includes(formarType)) {
+	if (validPost.includes(formerType)) {
 		return await deleteNote(actor, uri);
-	} else if (validActor.includes(formarType)) {
+	} else if (validActor.includes(formerType)) {
 		return await deleteActor(actor, uri);
 	} else {
-		return `Unknown type ${formarType}`;
+		return `Unknown type ${formerType}`;
 	}
 };
diff --git a/packages/backend/src/remote/activitypub/kernel/undo/announce.ts b/packages/backend/src/remote/activitypub/kernel/undo/announce.ts
index c2ac31bf8d..417f39722f 100644
--- a/packages/backend/src/remote/activitypub/kernel/undo/announce.ts
+++ b/packages/backend/src/remote/activitypub/kernel/undo/announce.ts
@@ -8,6 +8,7 @@ export const undoAnnounce = async (actor: CacheableRemoteUser, activity: IAnnoun
 
 	const note = await Notes.findOneBy({
 		uri,
+		userId: actor.id,
 	});
 
 	if (!note) return 'skip: no such Announce';
diff --git a/packages/backend/src/services/note/reaction/create.ts b/packages/backend/src/services/note/reaction/create.ts
index 5a0948bca9..5cb7ebdcd1 100644
--- a/packages/backend/src/services/note/reaction/create.ts
+++ b/packages/backend/src/services/note/reaction/create.ts
@@ -27,6 +27,11 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note,
 		}
 	}
 
+	// check visibility
+	if (!await Notes.isVisibleForMe(note, user)) {
+		throw new IdentifiableError('68e9d2d1-48bf-42c2-b90a-b20e09fd3d48', 'Note not accessible for you.');
+	}
+
 	// TODO: cache
 	reaction = await toDbReaction(reaction, user.host);