VYPR
Medium severity5.4NVD Advisory· Published Jan 20, 2025· Updated Apr 15, 2026

CVE-2025-23221

CVE-2025-23221

Description

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards. This vulnerability allows a user to maneuver the Webfinger mechanism to perform a GET request to any internal resource on any Host, Port, URL combination regardless of present security mechanisms, and forcing the victim’s server into an infinite loop causing Denial of Service. Moreover, this issue can also be maneuvered into performing a Blind SSRF attack. This vulnerability is fixed in 1.0.14, 1.1.11, 1.2.11, and 1.3.4.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@fedify/fedifynpm
>= 1.0.13, < 1.0.141.0.14
@fedify/fedifynpm
>= 1.1.10, < 1.1.111.1.11
@fedify/fedifynpm
>= 1.2.10, < 1.2.111.2.11
@fedify/fedifynpm
>= 1.3.3, < 1.3.41.3.4

Patches

10
8be3c2038eeb

`lookupWebFinger()`: avoid SSRF attacks

https://github.com/dahlia/fedifyHong MinheeJan 18, 2025via ghsa
3 files changed · +25 1
  • CHANGES.md+5 0 modified
    @@ -19,6 +19,11 @@ To be released.
             could lead to a security breach.  Now it follows only the same scheme
             as the original request.
     
    +     -  Fixed a security vulnerability where the `lookupWebFinger()` function
    +        had followed the redirects to the private network addresses, which
    +        could lead to a SSRF attack.  Now it follows only the public network
    +        addresses.
    +
     
     Version 1.0.13
     --------------
    
  • src/webfinger/lookup.test.ts+18 1 modified
    @@ -1,6 +1,7 @@
    -import { assertEquals } from "@std/assert";
    +import { assertEquals, assertRejects } from "@std/assert";
     import { deadline } from "@std/async/deadline";
     import * as mf from "mock_fetch";
    +import { UrlError } from "../runtime/url.ts";
     import { test } from "../testing/mod.ts";
     import type { ResourceDescriptor } from "./jrd.ts";
     import { lookupWebFinger } from "./lookup.ts";
    @@ -122,6 +123,22 @@ test("lookupWebFinger()", async (t) => {
         assertEquals(await lookupWebFinger("acct:johndoe@example.com"), null);
       });
     
    +  mf.mock(
    +    "GET@/.well-known/webfinger",
    +    (_) =>
    +      new Response("", {
    +        status: 302,
    +        headers: { Location: "https://localhost/" },
    +      }),
    +  );
    +
    +  await t.step("redirection to private address", async () => {
    +    await assertRejects(
    +      () => lookupWebFinger("acct:johndoe@example.com"),
    +      UrlError,
    +    );
    +  });
    +
       mf.uninstall();
     });
     
    
  • src/webfinger/lookup.ts+2 0 modified
    @@ -1,4 +1,5 @@
     import { getLogger } from "@logtape/logtape";
    +import { validatePublicUrl } from "../runtime/url.ts";
     import type { ResourceDescriptor } from "./jrd.ts";
     
     const logger = getLogger(["fedify", "webfinger", "lookup"]);
    @@ -35,6 +36,7 @@ export async function lookupWebFinger(
           { url: url.href },
         );
         let response: Response;
    +    await validatePublicUrl(url.href);
         try {
           response = await fetch(url, {
             headers: { Accept: "application/jrd+json" },
    
c505eb82fcd6

Make `lookupWebFinger()` to enforce protocol consistency

https://github.com/dahlia/fedifyHong MinheeJan 18, 2025via ghsa
3 files changed · +35 3
  • CHANGES.md+10 3 modified
    @@ -8,9 +8,16 @@ Version 1.0.14
     
     To be released.
     
    - -  Fixed a security vulnerability where the `lookupWebFinger()` function had
    -    followed the infinite number of redirects, which could lead to a denial of
    -    service attack.  Now it follows up to 5 redirects.
    + -  Fixed several security vulnerabilities of the `lookupWebFinger()` function.
    +
    +     -  Fixed a security vulnerability where the `lookupWebFinger()` function
    +        had followed the infinite number of redirects, which could lead to
    +        a denial of service attack.  Now it follows up to 5 redirects.
    +
    +     -  Fixed a security vulnerability where the `lookupWebFinger()` function
    +        had followed the redirects to other than the HTTP/HTTPS schemes, which
    +        could lead to a security breach.  Now it follows only the same scheme
    +        as the original request.
     
     
     Version 1.0.13
    
  • src/webfinger/lookup.test.ts+13 0 modified
    @@ -109,6 +109,19 @@ test("lookupWebFinger()", async (t) => {
         assertEquals(result, null);
       });
     
    +  mf.mock(
    +    "GET@/.well-known/webfinger",
    +    (_) =>
    +      new Response("", {
    +        status: 302,
    +        headers: { Location: "ftp://example.com/" },
    +      }),
    +  );
    +
    +  await t.step("redirection to different protocol", async () => {
    +    assertEquals(await lookupWebFinger("acct:johndoe@example.com"), null);
    +  });
    +
       mf.uninstall();
     });
     
    
  • src/webfinger/lookup.ts+12 0 modified
    @@ -64,6 +64,18 @@ export async function lookupWebFinger(
             response.headers.get("Location")!,
             response.url == null || response.url === "" ? url : response.url,
           );
    +      if (redirectedUrl.protocol !== url.protocol) {
    +        logger.error(
    +          "Redirected to a different protocol ({protocol} to " +
    +            "{redirectedProtocol}) while fetching WebFinger resource " +
    +            "descriptor.",
    +          {
    +            protocol: url.protocol,
    +            redirectedProtocol: redirectedUrl.protocol,
    +          },
    +        );
    +        return null;
    +      }
           url = redirectedUrl;
           continue;
         }
    
e921134dd509

`lookupWebFinger()`: avoid infinite redirection

https://github.com/dahlia/fedifyHong MinheeJan 18, 2025via ghsa
3 files changed · +36 1
  • CHANGES.md+4 0 modified
    @@ -8,6 +8,10 @@ Version 1.0.14
     
     To be released.
     
    + -  Fixed a security vulnerability where the `lookupWebFinger()` function had
    +    followed the infinite number of redirects, which could lead to a denial of
    +    service attack.  Now it follows up to 5 redirects.
    +
     
     Version 1.0.13
     --------------
    
  • src/webfinger/lookup.test.ts+18 0 modified
    @@ -1,4 +1,5 @@
     import { assertEquals } from "@std/assert";
    +import { deadline } from "@std/async/deadline";
     import * as mf from "mock_fetch";
     import { test } from "../testing/mod.ts";
     import type { ResourceDescriptor } from "./jrd.ts";
    @@ -91,6 +92,23 @@ test("lookupWebFinger()", async (t) => {
         assertEquals(await lookupWebFinger("acct:johndoe@example.com"), expected);
       });
     
    +  mf.mock(
    +    "GET@/.well-known/webfinger",
    +    (_) =>
    +      new Response("", {
    +        status: 302,
    +        headers: { Location: "/.well-known/webfinger" },
    +      }),
    +  );
    +
    +  await t.step("infinite redirection", async () => {
    +    const result = await deadline(
    +      lookupWebFinger("acct:johndoe@example.com"),
    +      2000,
    +    );
    +    assertEquals(result, null);
    +  });
    +
       mf.uninstall();
     });
     
    
  • src/webfinger/lookup.ts+14 1 modified
    @@ -3,6 +3,8 @@ import type { ResourceDescriptor } from "./jrd.ts";
     
     const logger = getLogger(["fedify", "webfinger", "lookup"]);
     
    +const MAX_REDIRECTION = 5; // TODO: Make this configurable.
    +
     /**
      * Looks up a WebFinger resource.
      * @param resource The resource URL to look up.
    @@ -26,6 +28,7 @@ export async function lookupWebFinger(
       }
       let url = new URL(`${protocol}//${server}/.well-known/webfinger`);
       url.searchParams.set("resource", resource.href);
    +  let redirected = 0;
       while (true) {
         logger.debug(
           "Fetching WebFinger resource descriptor from {url}...",
    @@ -48,10 +51,20 @@ export async function lookupWebFinger(
           response.status >= 300 && response.status < 400 &&
           response.headers.has("Location")
         ) {
    -      url = new URL(
    +      redirected++;
    +      if (redirected >= MAX_REDIRECTION) {
    +        logger.error(
    +          "Too many redirections ({redirections}) while fetching WebFinger " +
    +            "resource descriptor.",
    +          { redirections: redirected },
    +        );
    +        return null;
    +      }
    +      const redirectedUrl = new URL(
             response.headers.get("Location")!,
             response.url == null || response.url === "" ? url : response.url,
           );
    +      url = redirectedUrl;
           continue;
         }
         if (!response.ok) {
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.