Unverified Commit 1c9c8bfa authored by Hong Minhee's avatar Hong Minhee
Browse files

Fix vulnerability in getActorHandle() function

The `getActorHandle()` function had a vulnerability where it trusted the hostname of WebFinger aliases that did not match the hostname of the actor ID. This vulnerability has been fixed by adding a check to ensure that the hostname matches before returning the actor handle.
parent 8362c5af
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -8,6 +8,10 @@ Version 0.12.3

To be released.

 -  Fixed a vulnerability where the `getActorHandle()` function had trusted
    the hostname of WebFinger aliases that had not matched the hostname of the
    actor ID (URI).


Version 0.12.2
--------------
+13 −10
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ test("getActorHandle()", async (t) => {
    "GET@/.well-known/webfinger",
    (_) =>
      new Response(
        JSON.stringify({ subject: "acct:john@example.com" }),
        JSON.stringify({ subject: "acct:johndoe@foo.example.com" }),
        { headers: { "Content-Type": "application/jrd+json" } },
      ),
  );
@@ -112,15 +112,15 @@ test("getActorHandle()", async (t) => {
  });

  await t.step("WebFinger subject", async () => {
    assertEquals(await getActorHandle(actor), "@john@example.com");
    assertEquals(await getActorHandle(actor), "@johndoe@foo.example.com");
    assertEquals(
      await getActorHandle(actor, { trimLeadingAt: true }),
      "john@example.com",
      "johndoe@foo.example.com",
    );
    assertEquals(await getActorHandle(actorId), "@john@example.com");
    assertEquals(await getActorHandle(actorId), "@johndoe@foo.example.com");
    assertEquals(
      await getActorHandle(actorId, { trimLeadingAt: true }),
      "john@example.com",
      "johndoe@foo.example.com",
    );
  });

@@ -130,22 +130,25 @@ test("getActorHandle()", async (t) => {
      new Response(
        JSON.stringify({
          subject: "https://foo.example.com/@john",
          aliases: ["acct:john@bar.example.com"],
          aliases: [
            "acct:john@bar.example.com",
            "acct:johndoe@foo.example.com",
          ],
        }),
        { headers: { "Content-Type": "application/jrd+json" } },
      ),
  );

  await t.step("WebFinger aliases", async () => {
    assertEquals(await getActorHandle(actor), "@john@bar.example.com");
    assertEquals(await getActorHandle(actor), "@johndoe@foo.example.com");
    assertEquals(
      await getActorHandle(actor, { trimLeadingAt: true }),
      "john@bar.example.com",
      "johndoe@foo.example.com",
    );
    assertEquals(await getActorHandle(actorId), "@john@bar.example.com");
    assertEquals(await getActorHandle(actorId), "@johndoe@foo.example.com");
    assertEquals(
      await getActorHandle(actorId, { trimLeadingAt: true }),
      "john@bar.example.com",
      "johndoe@foo.example.com",
    );
  });

+2 −0
Original line number Diff line number Diff line
@@ -114,6 +114,8 @@ export async function getActorHandle(
      for (const alias of aliases) {
        const match = alias.match(/^acct:([^@]+)@([^@]+)$/);
        if (match != null) {
          const hostname = new URL(`https://${match[2]}/`).hostname;
          if (hostname !== actorId.hostname) continue;
          return normalizeActorHandle(`@${match[1]}@${match[2]}`, options);
        }
      }