From 122ad4603a5fa09a8a26f0a419b85b5dc56d7fe3 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Thu, 3 Jul 2025 10:56:07 -0700 Subject: [PATCH 1/3] Use correct Endpoint host and WebFinger domains in tests --- .../web_finger/web_finger_controller_test.exs | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/test/pleroma/web/web_finger/web_finger_controller_test.exs b/test/pleroma/web/web_finger/web_finger_controller_test.exs index be44e3a8b..a0f6663b4 100644 --- a/test/pleroma/web/web_finger/web_finger_controller_test.exs +++ b/test/pleroma/web/web_finger/web_finger_controller_test.exs @@ -34,6 +34,9 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do end test "Webfinger JRD" do + clear_config([Pleroma.Web.Endpoint, :url, :host], "hyrule.world") + clear_config([Pleroma.Web.WebFinger, :domain], "hyrule.world") + user = insert(:user, ap_id: "https://hyrule.world/users/zelda", @@ -43,10 +46,10 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do response = build_conn() |> put_req_header("accept", "application/jrd+json") - |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") + |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@hyrule.world") |> json_response(200) - assert response["subject"] == "acct:#{user.nickname}@localhost" + assert response["subject"] == "acct:#{user.nickname}@hyrule.world" assert response["aliases"] == [ "https://hyrule.world/users/zelda", @@ -55,6 +58,9 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do end test "Webfinger defaults to JSON when no Accept header is provided" do + clear_config([Pleroma.Web.Endpoint, :url, :host], "hyrule.world") + clear_config([Pleroma.Web.WebFinger, :domain], "hyrule.world") + user = insert(:user, ap_id: "https://hyrule.world/users/zelda", @@ -63,10 +69,10 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do response = build_conn() - |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") + |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@hyrule.world") |> json_response(200) - assert response["subject"] == "acct:#{user.nickname}@localhost" + assert response["subject"] == "acct:#{user.nickname}@hyrule.world" assert response["aliases"] == [ "https://hyrule.world/users/zelda", @@ -102,6 +108,9 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do end test "Webfinger XML" do + clear_config([Pleroma.Web.Endpoint, :url, :host], "hyrule.world") + clear_config([Pleroma.Web.WebFinger, :domain], "hyrule.world") + user = insert(:user, ap_id: "https://hyrule.world/users/zelda", @@ -129,6 +138,9 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do end test "Returns JSON when format is not supported" do + clear_config([Pleroma.Web.Endpoint, :url, :host], "hyrule.world") + clear_config([Pleroma.Web.WebFinger, :domain], "hyrule.world") + user = insert(:user, ap_id: "https://hyrule.world/users/zelda", @@ -138,10 +150,10 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do response = build_conn() |> put_req_header("accept", "text/html") - |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") + |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@hyrule.world") |> json_response(200) - assert response["subject"] == "acct:#{user.nickname}@localhost" + assert response["subject"] == "acct:#{user.nickname}@hyrule.world" assert response["aliases"] == [ "https://hyrule.world/users/zelda", From 736686b4e2b6e37408b2e46b5acfd4284ddd17c3 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Thu, 3 Jul 2025 11:19:52 -0700 Subject: [PATCH 2/3] Add specific tests for Webfinger aliases / also_known_as Also reorganize similar tests to be grouped together --- .../web_finger/web_finger_controller_test.exs | 165 ++++++++++++------ 1 file changed, 108 insertions(+), 57 deletions(-) diff --git a/test/pleroma/web/web_finger/web_finger_controller_test.exs b/test/pleroma/web/web_finger/web_finger_controller_test.exs index a0f6663b4..ef52a4b85 100644 --- a/test/pleroma/web/web_finger/web_finger_controller_test.exs +++ b/test/pleroma/web/web_finger/web_finger_controller_test.exs @@ -33,28 +33,46 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do assert match?(^response_xml, expected_xml) end - test "Webfinger JRD" do - clear_config([Pleroma.Web.Endpoint, :url, :host], "hyrule.world") - clear_config([Pleroma.Web.WebFinger, :domain], "hyrule.world") + describe "Webfinger" do + test "JRD" do + clear_config([Pleroma.Web.Endpoint, :url, :host], "hyrule.world") + clear_config([Pleroma.Web.WebFinger, :domain], "hyrule.world") - user = - insert(:user, - ap_id: "https://hyrule.world/users/zelda", - also_known_as: ["https://mushroom.kingdom/users/toad"] - ) + user = + insert(:user, + ap_id: "https://hyrule.world/users/zelda" + ) - response = - build_conn() - |> put_req_header("accept", "application/jrd+json") - |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@hyrule.world") - |> json_response(200) + response = + build_conn() + |> put_req_header("accept", "application/jrd+json") + |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@hyrule.world") + |> json_response(200) - assert response["subject"] == "acct:#{user.nickname}@hyrule.world" + assert response["subject"] == "acct:#{user.nickname}@hyrule.world" - assert response["aliases"] == [ - "https://hyrule.world/users/zelda", - "https://mushroom.kingdom/users/toad" - ] + assert response["aliases"] == [ + "https://hyrule.world/users/zelda" + ] + end + + test "XML" do + clear_config([Pleroma.Web.Endpoint, :url, :host], "hyrule.world") + clear_config([Pleroma.Web.WebFinger, :domain], "hyrule.world") + + user = + insert(:user, + ap_id: "https://hyrule.world/users/zelda" + ) + + response = + build_conn() + |> put_req_header("accept", "application/xrd+xml") + |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") + |> response(200) + + assert response =~ "https://hyrule.world/users/zelda" + end end test "Webfinger defaults to JSON when no Accept header is provided" do @@ -63,8 +81,7 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do user = insert(:user, - ap_id: "https://hyrule.world/users/zelda", - also_known_as: ["https://mushroom.kingdom/users/toad"] + ap_id: "https://hyrule.world/users/zelda" ) response = @@ -75,11 +92,63 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do assert response["subject"] == "acct:#{user.nickname}@hyrule.world" assert response["aliases"] == [ - "https://hyrule.world/users/zelda", - "https://mushroom.kingdom/users/toad" + "https://hyrule.world/users/zelda" ] end + describe "Webfinger returns also_known_as / aliases in the response" do + test "JSON" do + clear_config([Pleroma.Web.Endpoint, :url, :host], "hyrule.world") + clear_config([Pleroma.Web.WebFinger, :domain], "hyrule.world") + + user = + insert(:user, + ap_id: "https://hyrule.world/users/zelda", + also_known_as: [ + "https://mushroom.kingdom/users/toad", + "https://luigi.mansion/users/kingboo" + ] + ) + + response = + build_conn() + |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@hyrule.world") + |> json_response(200) + + assert response["subject"] == "acct:#{user.nickname}@hyrule.world" + + assert response["aliases"] == [ + "https://hyrule.world/users/zelda", + "https://mushroom.kingdom/users/toad", + "https://luigi.mansion/users/kingboo" + ] + end + + test "XML" do + clear_config([Pleroma.Web.Endpoint, :url, :host], "hyrule.world") + clear_config([Pleroma.Web.WebFinger, :domain], "hyrule.world") + + user = + insert(:user, + ap_id: "https://hyrule.world/users/zelda", + also_known_as: [ + "https://mushroom.kingdom/users/toad", + "https://luigi.mansion/users/kingboo" + ] + ) + + response = + build_conn() + |> put_req_header("accept", "application/xrd+xml") + |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") + |> response(200) + + assert response =~ "https://hyrule.world/users/zelda" + assert response =~ "https://mushroom.kingdom/users/toad" + assert response =~ "https://luigi.mansion/users/kingboo" + end + end + test "reach user on tld, while pleroma is running on subdomain" do clear_config([Pleroma.Web.Endpoint, :url, :host], "sub.example.com") @@ -97,44 +166,26 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do assert response["aliases"] == ["https://sub.example.com/users/#{user.nickname}"] end - test "it returns 404 when user isn't found (JSON)" do - result = - build_conn() - |> put_req_header("accept", "application/jrd+json") - |> get("/.well-known/webfinger?resource=acct:jimm@localhost") - |> json_response(404) + describe "it returns 404 when user isn't found" do + test "JSON" do + result = + build_conn() + |> put_req_header("accept", "application/jrd+json") + |> get("/.well-known/webfinger?resource=acct:jimm@localhost") + |> json_response(404) - assert result == "Couldn't find user" - end + assert result == "Couldn't find user" + end - test "Webfinger XML" do - clear_config([Pleroma.Web.Endpoint, :url, :host], "hyrule.world") - clear_config([Pleroma.Web.WebFinger, :domain], "hyrule.world") + test "XML" do + result = + build_conn() + |> put_req_header("accept", "application/xrd+xml") + |> get("/.well-known/webfinger?resource=acct:jimm@localhost") + |> response(404) - user = - insert(:user, - ap_id: "https://hyrule.world/users/zelda", - also_known_as: ["https://mushroom.kingdom/users/toad"] - ) - - response = - build_conn() - |> put_req_header("accept", "application/xrd+xml") - |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") - |> response(200) - - assert response =~ "https://hyrule.world/users/zelda" - assert response =~ "https://mushroom.kingdom/users/toad" - end - - test "it returns 404 when user isn't found (XML)" do - result = - build_conn() - |> put_req_header("accept", "application/xrd+xml") - |> get("/.well-known/webfinger?resource=acct:jimm@localhost") - |> response(404) - - assert result == "Couldn't find user" + assert result == "Couldn't find user" + end end test "Returns JSON when format is not supported" do From 17987e39908d8771b844142d62fcbfa795562815 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Thu, 3 Jul 2025 12:08:36 -0700 Subject: [PATCH 3/3] Enforce an exact domain match for WebFinger resolution The regex was not being terminated with an $ --- changelog.d/webfinger-resolution.fix | 1 + lib/pleroma/web/web_finger.ex | 4 ++-- test/pleroma/web/web_finger_test.exs | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 changelog.d/webfinger-resolution.fix diff --git a/changelog.d/webfinger-resolution.fix b/changelog.d/webfinger-resolution.fix new file mode 100644 index 000000000..71b927bb0 --- /dev/null +++ b/changelog.d/webfinger-resolution.fix @@ -0,0 +1 @@ +Enforce an exact domain match for WebFinger resolution diff --git a/lib/pleroma/web/web_finger.ex b/lib/pleroma/web/web_finger.ex index e653b3338..a53d58caa 100644 --- a/lib/pleroma/web/web_finger.ex +++ b/lib/pleroma/web/web_finger.ex @@ -35,9 +35,9 @@ defmodule Pleroma.Web.WebFinger do regex = if webfinger_domain = Pleroma.Config.get([__MODULE__, :domain]) do - ~r/(acct:)?(?[a-z0-9A-Z_\.-]+)@(#{host}|#{webfinger_domain})/ + ~r/(acct:)?(?[a-z0-9A-Z_\.-]+)@(#{host}|#{webfinger_domain})$/ else - ~r/(acct:)?(?[a-z0-9A-Z_\.-]+)@#{host}/ + ~r/(acct:)?(?[a-z0-9A-Z_\.-]+)@#{host}$/ end with %{"username" => username} <- Regex.named_captures(regex, resource), diff --git a/test/pleroma/web/web_finger_test.exs b/test/pleroma/web/web_finger_test.exs index aefe7b0c2..923074ed5 100644 --- a/test/pleroma/web/web_finger_test.exs +++ b/test/pleroma/web/web_finger_test.exs @@ -39,6 +39,23 @@ defmodule Pleroma.Web.WebFingerTest do end end + test "requires exact match for Endpoint host or WebFinger domain" do + clear_config([Pleroma.Web.WebFinger, :domain], "pleroma.dev") + user = insert(:user) + + assert {:error, "Couldn't find user"} == + WebFinger.webfinger("#{user.nickname}@#{Pleroma.Web.Endpoint.host()}xxxx", "JSON") + + assert {:error, "Couldn't find user"} == + WebFinger.webfinger("#{user.nickname}@pleroma.devxxxx", "JSON") + + assert {:ok, _} = + WebFinger.webfinger("#{user.nickname}@#{Pleroma.Web.Endpoint.host()}", "JSON") + + assert {:ok, _} = + WebFinger.webfinger("#{user.nickname}@pleroma.dev", "JSON") + end + describe "fingering" do test "returns error for nonsensical input" do assert {:error, _} = WebFinger.finger("bliblablu")