Unverified Commit 6eef6fc6 authored by Hong Minhee's avatar Hong Minhee
Browse files

Fix handling of private addresses in `Context.lookupObject()`

parent 5807f827
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -8,6 +8,14 @@ Version 1.3.5

To be released.

 -  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
-------------
+56 −0
Original line number Diff line number Diff line
@@ -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();

+4 −0
Original line number Diff line number Diff line
@@ -372,6 +372,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;
@@ -429,6 +430,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,
@@ -2882,6 +2884,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,
    });
  }

+3 −0
Original line number Diff line number Diff line
@@ -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) {
+2 −6
Original line number Diff line number Diff line
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";
@@ -133,10 +132,7 @@ test("lookupWebFinger()", async (t) => {
  );

  await t.step("redirection to private address", async () => {
    await assertRejects(
      () => lookupWebFinger("acct:johndoe@example.com"),
      UrlError,
    );
    assertEquals(await lookupWebFinger("acct:johndoe@example.com"), null);
  });

  mf.uninstall();
Loading