From 18353973859d20c4be96d7b9ea91da35cb92cf52 Mon Sep 17 00:00:00 2001
From: tamaina <tamaina@hotmail.co.jp>
Date: Mon, 26 Feb 2024 21:06:05 +0000
Subject: [PATCH] validate additionalPublicKeys

---
 .../core/activitypub/ApDbResolverService.ts   |  2 +-
 .../activitypub/models/ApPersonService.ts     | 31 +++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts
index 913070fdd4..6cce3951bd 100644
--- a/packages/backend/src/core/activitypub/ApDbResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts
@@ -152,7 +152,7 @@ export class ApDbResolverService implements OnApplicationShutdown {
 	@bindThis
 	public async getAuthUserFromApId(uri: string): Promise<{
 		user: MiRemoteUser;
-		key: MiUserPublickey | null;
+		key: MiUserPublickey[] | null;
 	} | null> {
 		const user = await this.apPersonService.resolvePerson(uri) as MiRemoteUser;
 		if (user.isDeleted) return null;
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index c31aa03261..4c1f79e1b1 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -194,6 +194,37 @@ export class ApPersonService implements OnModuleInit {
 			}
 		}
 
+		if (x.additionalPublicKeys) {
+			if (!x.publicKey) {
+				throw new Error('invalid Actor: additionalPublicKeys is set but publicKey is not');
+			}
+
+			if (!Array.isArray(x.additionalPublicKeys)) {
+				throw new Error('invalid Actor: additionalPublicKeys is not an array');
+			}
+
+			for (const key of x.additionalPublicKeys) {
+				if (typeof key.id !== 'string') {
+					throw new Error('invalid Actor: additionalPublicKeys.id is not a string');
+				}
+
+				const keyIdHost = this.punyHost(key.id);
+				if (keyIdHost !== expectHost) {
+					throw new Error('invalid Actor: additionalPublicKeys.id has different host');
+				}
+
+				if (!key.signature) {
+					throw new Error('invalid Actor: additionalPublicKeys.signature is not set');
+				}
+				if (typeof key.signature.type !== 'string') {
+					throw new Error('invalid Actor: additionalPublicKeys.signature.type is not a string');
+				}
+				if (typeof key.signature.signatureValue !== 'string') {
+					throw new Error('invalid Actor: additionalPublicKeys.signature.signatureValue is not a string');
+				}
+			}
+		}
+
 		return x;
 	}