Skip to content

Commit 8be3c20

Browse files
committed
lookupWebFinger(): avoid SSRF attacks
GHSA-c59p-wq67-24wx
1 parent c505eb8 commit 8be3c20

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

CHANGES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ To be released.
1919
could lead to a security breach. Now it follows only the same scheme
2020
as the original request.
2121

22+
- Fixed a security vulnerability where the `lookupWebFinger()` function
23+
had followed the redirects to the private network addresses, which
24+
could lead to a SSRF attack. Now it follows only the public network
25+
addresses.
26+
2227

2328
Version 1.0.13
2429
--------------

src/webfinger/lookup.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { assertEquals } from "@std/assert";
1+
import { assertEquals, assertRejects } from "@std/assert";
22
import { deadline } from "@std/async/deadline";
33
import * as mf from "mock_fetch";
4+
import { UrlError } from "../runtime/url.ts";
45
import { test } from "../testing/mod.ts";
56
import type { ResourceDescriptor } from "./jrd.ts";
67
import { lookupWebFinger } from "./lookup.ts";
@@ -122,6 +123,22 @@ test("lookupWebFinger()", async (t) => {
122123
assertEquals(await lookupWebFinger("acct:[email protected]"), null);
123124
});
124125

126+
mf.mock(
127+
"GET@/.well-known/webfinger",
128+
(_) =>
129+
new Response("", {
130+
status: 302,
131+
headers: { Location: "https://localhost/" },
132+
}),
133+
);
134+
135+
await t.step("redirection to private address", async () => {
136+
await assertRejects(
137+
() => lookupWebFinger("acct:[email protected]"),
138+
UrlError,
139+
);
140+
});
141+
125142
mf.uninstall();
126143
});
127144

src/webfinger/lookup.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { getLogger } from "@logtape/logtape";
2+
import { validatePublicUrl } from "../runtime/url.ts";
23
import type { ResourceDescriptor } from "./jrd.ts";
34

45
const logger = getLogger(["fedify", "webfinger", "lookup"]);
@@ -35,6 +36,7 @@ export async function lookupWebFinger(
3536
{ url: url.href },
3637
);
3738
let response: Response;
39+
await validatePublicUrl(url.href);
3840
try {
3941
response = await fetch(url, {
4042
headers: { Accept: "application/jrd+json" },

0 commit comments

Comments
 (0)