From 4e7c9a895d3d9ebb5f5f25339db62a387b26b4cd Mon Sep 17 00:00:00 2001 From: ojspp41 Date: Fri, 7 Aug 2026 16:27:59 +0900 Subject: [PATCH 1/2] Reject mismatched standalone key IDs Keep fetched key identities aligned with their requested URLs and cache entries. Add regression coverage for both CryptographicKey and Multikey rejection and negative caching while preserving actor lookup behavior. Fixes https://github.com/fedify-dev/fedify/issues/963 Assisted-by: Codex:gpt-5.6-sol --- CHANGES.md | 8 ++++ changes.d/fedify/mismatched-key-id.md | 5 +++ packages/fedify/src/sig/key.test.ts | 59 +++++++++++++++++++++++++++ packages/fedify/src/sig/key.ts | 5 ++- 4 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 changes.d/fedify/mismatched-key-id.md diff --git a/CHANGES.md b/CHANGES.md index a22ea5651..132084f83 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,14 @@ Version 2.0.25 To be released. +### @fedify/fedify + + - Standalone key documents whose `id` differs from the requested key URL are + now rejected instead of being cached under the wrong URL. [[#963]] by + ojspp41 + +[#963]: https://github.com/fedify-dev/fedify/issues/963 + Version 2.0.24 -------------- diff --git a/changes.d/fedify/mismatched-key-id.md b/changes.d/fedify/mismatched-key-id.md new file mode 100644 index 000000000..63d532e9d --- /dev/null +++ b/changes.d/fedify/mismatched-key-id.md @@ -0,0 +1,5 @@ + - Standalone key documents whose `id` differs from the requested key URL are + now rejected instead of being cached under the wrong URL. [[#963]] by + ojspp41 + +[#963]: https://github.com/fedify-dev/fedify/issues/963 diff --git a/packages/fedify/src/sig/key.test.ts b/packages/fedify/src/sig/key.test.ts index 09c002bb8..de0f6d934 100644 --- a/packages/fedify/src/sig/key.test.ts +++ b/packages/fedify/src/sig/key.test.ts @@ -352,6 +352,65 @@ test("fetchKey()", async () => { ); }); +test("fetchKey() rejects standalone keys with a mismatched id", async () => { + for ( + const { keyId, standaloneKey, fetch } of [ + { + keyId: "https://example.com/key", + standaloneKey: rsaPublicKey1, + fetch: (keyId: string, options: FetchKeyOptions) => + fetchKey(keyId, CryptographicKey, options), + }, + { + keyId: "https://example.com/multikey", + standaloneKey: ed25519Multikey, + fetch: (keyId: string, options: FetchKeyOptions) => + fetchKey(keyId, Multikey, options), + }, + ] + ) { + const cache: Record = {}; + const options: FetchKeyOptions = { + async documentLoader(resource) { + if (resource === keyId) { + const document = await standaloneKey.toJsonLd({ + contextLoader: mockDocumentLoader, + }); + return { + contextUrl: null, + documentUrl: resource, + document: { + ...document as Record, + id: "https://example.com/different-key", + }, + }; + } + return await mockDocumentLoader(resource); + }, + contextLoader: mockDocumentLoader, + keyCache: { + get(keyId) { + return Promise.resolve(cache[keyId.href]); + }, + set(keyId, key) { + cache[keyId.href] = key; + return Promise.resolve(); + }, + } satisfies KeyCache, + }; + + assertEquals(await fetch(keyId, options), { + key: null, + cached: false, + }); + assertEquals(cache, { [keyId]: null }); + assertEquals(await fetch(keyId, options), { + key: null, + cached: true, + }); + } +}); + test("fetchKey() returns null for a malformed actor publicKey", async () => { const actorId = "https://example.com/malformed-public-key"; const keyId = "https://example.com/malformed-public-key#main-key"; diff --git a/packages/fedify/src/sig/key.ts b/packages/fedify/src/sig/key.ts index 757201f97..1928e145c 100644 --- a/packages/fedify/src/sig/key.ts +++ b/packages/fedify/src/sig/key.ts @@ -323,7 +323,10 @@ async function fetchKeyInternal( } } let key: T | null = null; - if (object instanceof cls) key = object; + if ( + object instanceof cls && + (object.id == null || object.id.href === keyId) + ) key = object; else if (isActor(object)) { // Treat malformed remote actor keys as missing keys. // @ts-ignore: cls is either CryptographicKey or Multikey From 617bfbb01597d666c67909aaa054e98dbb5396d0 Mon Sep 17 00:00:00 2001 From: ojspp41 Date: Wed, 19 Aug 2026 23:17:40 +0900 Subject: [PATCH 2/2] Correct changelog attribution Reference both the accepted issue and this pull request, close the reference parenthesis, and credit the contributor by their real name. Assisted-by: Codex:gpt-5.6-sol --- CHANGES.md | 5 +++-- changes.d/fedify/mismatched-key-id.md | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 132084f83..ac5155bcc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,10 +11,11 @@ To be released. ### @fedify/fedify - Standalone key documents whose `id` differs from the requested key URL are - now rejected instead of being cached under the wrong URL. [[#963]] by - ojspp41 + now rejected instead of being cached under the wrong URL. + ([#963], [#980] by Junseok Oh) [#963]: https://github.com/fedify-dev/fedify/issues/963 +[#980]: https://github.com/fedify-dev/fedify/issues/980 Version 2.0.24 diff --git a/changes.d/fedify/mismatched-key-id.md b/changes.d/fedify/mismatched-key-id.md index 63d532e9d..5445295e7 100644 --- a/changes.d/fedify/mismatched-key-id.md +++ b/changes.d/fedify/mismatched-key-id.md @@ -1,5 +1,6 @@ - Standalone key documents whose `id` differs from the requested key URL are - now rejected instead of being cached under the wrong URL. [[#963]] by - ojspp41 + now rejected instead of being cached under the wrong URL. + ([#963], [#980] by Junseok Oh) [#963]: https://github.com/fedify-dev/fedify/issues/963 +[#980]: https://github.com/fedify-dev/fedify/issues/980