From 2a80a07854610fee32bd8a668ba7e433c14a94c4 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Jun 2026 10:32:16 +0200 Subject: [PATCH] Fix fetching unknown key when it's not the actor's first, and add error handling for unavailable keys (#39512) --- .../activitypub/fetch_remote_key_service.rb | 2 +- .../activitypub/process_account_service.rb | 1 + .../fetch_remote_key_service_spec.rb | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/app/services/activitypub/fetch_remote_key_service.rb b/app/services/activitypub/fetch_remote_key_service.rb index 9b61ac6086..378401c574 100644 --- a/app/services/activitypub/fetch_remote_key_service.rb +++ b/app/services/activitypub/fetch_remote_key_service.rb @@ -77,6 +77,6 @@ class ActivityPub::FetchRemoteKeyService < BaseService end def confirmed_owner? - value_or_id(@owner['publicKey']) == @json['id'] + as_array(@owner['publicKey']).map { |value| value_or_id(value) }.include?(@json['id']) end end diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index d027c0c3a7..71d8e476e6 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -290,6 +290,7 @@ class ActivityPub::ProcessAccountService < BaseService # Key is fetched without ID validation because of a GoToSocial bug value = fetch_resource_without_id_validation(key_id) + next if value.blank? # Special handling for GoToSocial which returns the whole actor for the key ID value = first_of_value(value['publicKey']) if value.is_a?(Hash) && value.key?('publicKey') diff --git a/spec/services/activitypub/fetch_remote_key_service_spec.rb b/spec/services/activitypub/fetch_remote_key_service_spec.rb index fc7dfb3c42..fe418a1b1a 100644 --- a/spec/services/activitypub/fetch_remote_key_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_key_service_spec.rb @@ -81,6 +81,25 @@ RSpec.describe ActivityPub::FetchRemoteKeyService do expect(keypair.uri).to eq public_key_id expect(keypair.public_key).to eq public_key_pem end + + context 'when there are multiple keys' do + let(:actor_public_key) do + [ + 'https://example.com/unavailable-key.json', + public_key_id, + ] + end + + before do + stub_request(:get, 'https://example.com/unavailable-key.json').to_return(status: 404) + end + + it 'returns the expected account' do + expect(keypair.account.uri).to eq 'https://example.com/alice' + expect(keypair.uri).to eq public_key_id + expect(keypair.public_key).to eq public_key_pem + end + end end context 'when the key and owner do not match' do