about summary refs log tree commit diff
path: root/spec/services/activitypub
diff options
context:
space:
mode:
authorClaire <claire.github-309c@sitedethib.com>2022-12-07 00:15:24 +0100
committerGitHub <noreply@github.com>2022-12-07 00:15:24 +0100
commitc8849d6ceecfdb9c18284fcc57a7e29019b4cd05 (patch)
tree13d33d7d66d6e996f9138ee733dba0e367f52f9a /spec/services/activitypub
parent98a9347dd735f1d7040175d243b8af8ac3a4ebca (diff)
Fix unbounded recursion in account discovery (#22025)
* Fix trying to fetch posts from other users when fetching featured posts

* Rate-limit discovery of new subdomains

* Put a limit on recursively discovering new accounts
Diffstat (limited to 'spec/services/activitypub')
-rw-r--r--spec/services/activitypub/process_account_service_spec.rb94
1 files changed, 94 insertions, 0 deletions
diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb
index 7728b9ba8..2b20d17b1 100644
--- a/spec/services/activitypub/process_account_service_spec.rb
+++ b/spec/services/activitypub/process_account_service_spec.rb
@@ -109,4 +109,98 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
       end
     end
   end
+
+  context 'discovering many subdomains in a short timeframe' do
+    before do
+      stub_const 'ActivityPub::ProcessAccountService::SUBDOMAINS_RATELIMIT', 5
+    end
+
+    let(:subject) do
+      8.times do |i|
+        domain = "test#{i}.testdomain.com"
+        json = {
+          id: "https://#{domain}/users/1",
+          type: 'Actor',
+          inbox: "https://#{domain}/inbox",
+        }.with_indifferent_access
+        described_class.new.call('alice', domain, json)
+      end
+    end
+
+    it 'creates at least some accounts' do
+      expect { subject }.to change { Account.remote.count }.by_at_least(2)
+    end
+
+    it 'creates no more account than the limit allows' do
+      expect { subject }.to change { Account.remote.count }.by_at_most(5)
+    end
+  end
+
+  context 'accounts referencing other accounts' do
+    before do
+      stub_const 'ActivityPub::ProcessAccountService::DISCOVERIES_PER_REQUEST', 5
+    end
+
+    let(:payload) do
+      {
+        '@context': ['https://www.w3.org/ns/activitystreams'],
+        id: 'https://foo.test/users/1',
+        type: 'Person',
+        inbox: 'https://foo.test/inbox',
+        featured: 'https://foo.test/users/1/featured',
+        preferredUsername: 'user1',
+      }.with_indifferent_access
+    end
+
+    before do
+      8.times do |i|
+        actor_json = {
+          '@context': ['https://www.w3.org/ns/activitystreams'],
+          id: "https://foo.test/users/#{i}",
+          type: 'Person',
+          inbox: 'https://foo.test/inbox',
+          featured: "https://foo.test/users/#{i}/featured",
+          preferredUsername: "user#{i}",
+        }.with_indifferent_access
+        status_json = {
+          '@context': ['https://www.w3.org/ns/activitystreams'],
+          id: "https://foo.test/users/#{i}/status",
+          attributedTo: "https://foo.test/users/#{i}",
+          type: 'Note',
+          content: "@user#{i + 1} test",
+          tag: [
+            {
+              type: 'Mention',
+              href: "https://foo.test/users/#{i + 1}",
+              name: "@user#{i + 1 }",
+            }
+          ],
+          to: [ 'as:Public', "https://foo.test/users/#{i + 1}" ]
+        }.with_indifferent_access
+        featured_json = {
+          '@context': ['https://www.w3.org/ns/activitystreams'],
+          id: "https://foo.test/users/#{i}/featured",
+          type: 'OrderedCollection',
+          totelItems: 1,
+          orderedItems: [status_json],
+        }.with_indifferent_access
+        webfinger = {
+          subject: "acct:user#{i}@foo.test",
+          links: [{ rel: 'self', href: "https://foo.test/users/#{i}" }],
+        }.with_indifferent_access
+        stub_request(:get, "https://foo.test/users/#{i}").to_return(status: 200, body: actor_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
+        stub_request(:get, "https://foo.test/users/#{i}/featured").to_return(status: 200, body: featured_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
+        stub_request(:get, "https://foo.test/users/#{i}/status").to_return(status: 200, body: status_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
+        stub_request(:get, "https://foo.test/.well-known/webfinger?resource=acct:user#{i}@foo.test").to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
+      end
+    end
+
+    it 'creates at least some accounts' do
+      expect { subject.call('user1', 'foo.test', payload) }.to change { Account.remote.count }.by_at_least(2)
+    end
+
+    it 'creates no more account than the limit allows' do
+      expect { subject.call('user1', 'foo.test', payload) }.to change { Account.remote.count }.by_at_most(5)
+    end
+  end
 end