CVE-2025-23221 Overview
Fedify is a TypeScript library for building federated server applications powered by ActivityPub and related standards. CVE-2025-23221 allows an attacker to abuse the WebFinger lookup mechanism to issue GET requests against any host, port, and URL combination, bypassing existing security controls. The flaw also enables attackers to force a victim server into an infinite redirect loop, producing a Denial of Service condition, and can be leveraged for Blind Server-Side Request Forgery (SSRF) [CWE-835]. Maintainers released fixes in Fedify versions 1.0.14, 1.1.11, 1.2.11, and 1.3.4.
Critical Impact
Remote unauthenticated attackers can trigger infinite loops causing Denial of Service and perform Blind SSRF against internal resources through the WebFinger endpoint.
Affected Products
- Fedify versions prior to 1.0.14
- Fedify 1.1.x versions prior to 1.1.11
- Fedify 1.2.x versions prior to 1.2.11 and 1.3.x versions prior to 1.3.4
Discovery Timeline
- 2025-01-20 - CVE-2025-23221 published to NVD
- 2026-06-17 - Last updated in NVD database
Technical Details for CVE-2025-23221
Vulnerability Analysis
The vulnerability resides in the lookupWebFinger() function within src/webfinger/lookup.ts. The function issues outbound HTTP requests to resolve WebFinger resources but fails to validate the target URL against internal address ranges and does not enforce protocol consistency during redirects. Additionally, the lookup routine lacked a maximum redirect count, permitting attacker-controlled servers to send a chain of redirects that never terminates.
An attacker who submits a crafted resource identifier to a Fedify-powered server can steer the outbound request to localhost, private network ranges, or arbitrary internal services. Because the response body is not returned to the attacker, this class of exploitation is classified as Blind SSRF, but timing and response codes can still leak information about internal infrastructure.
Root Cause
The root cause is missing input validation on the URL passed to lookupWebFinger() combined with unbounded redirect handling. Without URL allow-listing, protocol pinning, or redirect limits, the function trusted arbitrary redirect targets returned by remote servers, mapping directly to the [CWE-835] Loop with Unreachable Exit Condition weakness.
Attack Vector
An unauthenticated remote attacker triggers a WebFinger lookup by sending a request that references an attacker-controlled resource. The victim server issues the outbound HTTP GET, follows attacker-supplied redirects indefinitely, and either exhausts resources or reaches an internal target on behalf of the attacker.
// Patch: enforce a maximum redirect count in lookupWebFinger()
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.
*/
// Source: https://github.com/dahlia/fedify/commit/e921134dd5097586e4563ea80b9e8d1b5460a645
// Patch: enforce protocol consistency on redirects
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;
// Source: https://github.com/dahlia/fedify/commit/c505eb82fcd6b5b17174c6659c29721bc801ab9a
// Patch: validate that the target URL is public before requesting it
import { getLogger } from "@logtape/logtape";
import { validatePublicUrl } from "../runtime/url.ts";
import type { ResourceDescriptor } from "./jrd.ts";
const logger = getLogger(["fedify", "webfinger", "lookup"]);
// Source: https://github.com/dahlia/fedify/commit/8be3c2038eebf4ae12481683a1e809b314be3151
Detection Methods for CVE-2025-23221
Indicators of Compromise
- Repeated outbound requests from the Fedify process to 127.0.0.1, 169.254.169.254, or RFC1918 addresses.
- Sustained CPU or socket exhaustion tied to a single WebFinger request path (/.well-known/webfinger).
- Application logs showing long redirect chains originating from a single resource parameter.
Detection Strategies
- Inspect HTTP access logs for /.well-known/webfinger requests carrying resource values pointing at internal hostnames, IP literals, or non-https schemes.
- Correlate outbound network telemetry from the Fedify server with inbound WebFinger requests to identify SSRF pivots.
- Alert on process-level indicators such as growing file descriptor counts or thread counts on the Node.js runtime hosting Fedify.
Monitoring Recommendations
- Ingest application and network flow logs into a centralized analytics platform and pivot on the WebFinger endpoint.
- Track redirect counts per WebFinger lookup and flag any request that exceeds the new MAX_REDIRECTION limit of 5.
- Monitor for anomalous latency and 5xx spikes on the WebFinger route, which typically precede resource exhaustion.
How to Mitigate CVE-2025-23221
Immediate Actions Required
- Upgrade Fedify to 1.0.14, 1.1.11, 1.2.11, or 1.3.4 depending on the deployed release line.
- Audit reverse-proxy and egress firewall rules to block outbound traffic from the Fedify host to private IP ranges and metadata services.
- Rate limit unauthenticated requests to /.well-known/webfinger to reduce DoS exposure.
Patch Information
The fix is delivered across three commits: 8be3c20 introduces validatePublicUrl() to reject SSRF targets, c505eb8 enforces protocol consistency across redirects, and e921134 caps redirects at MAX_REDIRECTION = 5. Full details are available in the GitHub Security Advisory GHSA-c59p-wq67-24wx.
Workarounds
- Place Fedify behind an egress proxy that denies connections to internal address ranges and cloud metadata endpoints.
- Terminate WebFinger requests at a reverse proxy and validate the resource parameter before forwarding to Fedify.
- Impose per-source request quotas on the WebFinger endpoint until the upgrade can be deployed.
# Upgrade Fedify to a patched release using npm
npm install @fedify/fedify@^1.3.4
# Or pin a specific patched line, for example the 1.2.x branch
npm install @fedify/fedify@1.2.11
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

