Skip to content

Commit

Permalink
Merge tag '1.3.5'
Browse files Browse the repository at this point in the history
Fedify 1.3.5
  • Loading branch information
dahlia committed Jan 21, 2025
2 parents b9f34f4 + 330c5d1 commit fcb246e
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 8 deletions.
14 changes: 14 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ To be released.
[#195]: https://github.com/dahlia/fedify/issues/195


Version 1.3.5
-------------

Released on January 21, 2025.

- Fixed a bug where `CreateFederationOptions.allowPrivateAddress` option had
been ignored by the `Context.lookupObject()` method when it had taken
a fediverse handle.

- The `lookupWebFinger()` function became to silently return `null` when
it fails to fetch the WebFinger document due to accessing a private network
address, instead of throwing a `UrlError`.


Version 1.3.4
-------------

Expand Down
56 changes: 56 additions & 0 deletions src/federation/middleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,62 @@ test("FederationImpl.sendActivity()", async (t) => {
mf.uninstall();
});

test("ContextImpl.lookupObject()", async (t) => {
// Note that this test only checks if allowPrivateAddress option affects
// the ContextImpl.lookupObject() method. Other aspects of the method are
// tested in the lookupObject() tests.

mf.install();
mf.mock("GET@/.well-known/webfinger", () =>
new Response(
JSON.stringify({
subject: "acct:test@localhost",
links: [
{
rel: "self",
type: "application/activity+json",
href: "https://localhost/actor",
},
],
}),
{ headers: { "Content-Type": "application/jrd+json" } },
));
mf.mock("GET@/actor", () =>
new Response(
JSON.stringify({
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Person",
"id": "https://localhost/actor",
"preferredUsername": "test",
}),
{ headers: { "Content-Type": "application/activity+json" } },
));

await t.step("allowPrivateAddress: true", async () => {
const federation = createFederation<void>({
kv: new MemoryKvStore(),
allowPrivateAddress: true,
});
const ctx = federation.createContext(new URL("https://example.com/"));
const result = await ctx.lookupObject("@test@localhost");
assertInstanceOf(result, Person);
assertEquals(result.id, new URL("https://localhost/actor"));
assertEquals(result.preferredUsername, "test");
});

await t.step("allowPrivateAddress: false", async () => {
const federation = createFederation<void>({
kv: new MemoryKvStore(),
allowPrivateAddress: false,
});
const ctx = federation.createContext(new URL("https://example.com/"));
const result = await ctx.lookupObject("@test@localhost");
assertEquals(result, null);
});

mf.uninstall();
});

test("ContextImpl.sendActivity()", async (t) => {
mf.install();

Expand Down
4 changes: 4 additions & 0 deletions src/federation/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> {
documentLoader: DocumentLoader;
contextLoader: DocumentLoader;
authenticatedDocumentLoaderFactory: AuthenticatedDocumentLoaderFactory;
allowPrivateAddress: boolean;
userAgent?: GetUserAgentOptions | string;
onOutboxError?: OutboxErrorHandler;
signatureTimeWindow: Temporal.Duration | Temporal.DurationLike | false;
Expand Down Expand Up @@ -430,6 +431,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> {
}
}
const { allowPrivateAddress, userAgent } = options;
this.allowPrivateAddress = allowPrivateAddress ?? false;
this.documentLoader = options.documentLoader ?? kvCache({
loader: getDocumentLoader({ allowPrivateAddress, userAgent }),
kv: options.kv,
Expand Down Expand Up @@ -2894,6 +2896,8 @@ export class ContextImpl<TContextData> implements Context<TContextData> {
contextLoader: options.contextLoader ?? this.contextLoader,
userAgent: options.userAgent ?? this.federation.userAgent,
tracerProvider: options.tracerProvider ?? this.tracerProvider,
// @ts-ignore: `allowPrivateAddress` is not in the type definition.
allowPrivateAddress: this.federation.allowPrivateAddress,
});
}

Expand Down
3 changes: 3 additions & 0 deletions src/vocab/lookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ async function lookupObjectInternal(
const jrd = await lookupWebFinger(identifier, {
userAgent: options.userAgent,
tracerProvider: options.tracerProvider,
// @ts-ignore: `allowPrivateAddress` is not in the type definition.
allowPrivateAddress: "allowPrivateAddress" in options &&
options.allowPrivateAddress,
});
if (jrd?.links == null) return null;
for (const l of jrd.links) {
Expand Down
8 changes: 2 additions & 6 deletions src/webfinger/lookup.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { assertEquals, assertRejects } from "@std/assert";
import { assertEquals } 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";
Expand Down Expand Up @@ -133,10 +132,7 @@ test("lookupWebFinger()", async (t) => {
);

await t.step("redirection to private address", async () => {
await assertRejects(
() => lookupWebFinger("acct:[email protected]"),
UrlError,
);
assertEquals(await lookupWebFinger("acct:[email protected]"), null);
});

mf.uninstall();
Expand Down
17 changes: 15 additions & 2 deletions src/webfinger/lookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
getUserAgent,
type GetUserAgentOptions,
} from "../runtime/docloader.ts";
import { validatePublicUrl } from "../runtime/url.ts";
import { UrlError, validatePublicUrl } from "../runtime/url.ts";
import type { ResourceDescriptor } from "./jrd.ts";

const logger = getLogger(["fedify", "webfinger", "lookup"]);
Expand Down Expand Up @@ -109,7 +109,20 @@ async function lookupWebFingerInternal(
{ url: url.href },
);
let response: Response;
await validatePublicUrl(url.href);
if (!("allowPrivateAddress" in options) || !options.allowPrivateAddress) {
try {
await validatePublicUrl(url.href);
} catch (e) {
if (e instanceof UrlError) {
logger.error(
"Invalid URL for WebFinger resource descriptor: {error}",
{ error: e },
);
return null;
}
throw e;
}
}
try {
response = await fetch(url, {
headers: {
Expand Down

0 comments on commit fcb246e

Please sign in to comment.