@fedify/fedify 2.0.28-dev.1974 → 2.0.28-dev.1979

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/{builder-DBKy92BX.mjs → builder-CAAXTNeK.mjs} +3 -3
  2. package/dist/compat/mod.d.cts +1 -1
  3. package/dist/compat/mod.d.ts +1 -1
  4. package/dist/compat/transformers.test.mjs +1 -1
  5. package/dist/{context-DnsFj3yK.d.ts → context-DJ5oMnte.d.ts} +2 -1
  6. package/dist/{context-CJZHWLmz.d.cts → context-zLLwVY_G.d.cts} +2 -1
  7. package/dist/{deno-CGtm12Ft.mjs → deno-D3gZ1DsB.mjs} +1 -1
  8. package/dist/{docloader-_hXTUC-b.mjs → docloader-DIk3fEXZ.mjs} +2 -2
  9. package/dist/federation/builder.test.mjs +1 -1
  10. package/dist/federation/handler.test.mjs +4 -4
  11. package/dist/federation/idempotency.test.mjs +2 -2
  12. package/dist/federation/inbox.test.mjs +1 -1
  13. package/dist/federation/middleware.test.mjs +39 -7
  14. package/dist/federation/mod.cjs +1 -1
  15. package/dist/federation/mod.d.cts +2 -2
  16. package/dist/federation/mod.d.ts +2 -2
  17. package/dist/federation/mod.js +1 -1
  18. package/dist/federation/send.test.mjs +136 -3
  19. package/dist/federation/temporal.test.mjs +1 -1
  20. package/dist/federation/webfinger.test.mjs +1 -1
  21. package/dist/{http-BuaGj55w.cjs → http-BLqv_3ue.cjs} +1 -1
  22. package/dist/{http--P33qRwW.mjs → http-Bn3-am6C.mjs} +2 -2
  23. package/dist/{http-BP1pVF9m.js → http-Cx5dD1D_.js} +1 -1
  24. package/dist/{inbox-BZNyUPzW.mjs → inbox-DC8NbYIj.mjs} +1 -1
  25. package/dist/{key-rC9mW1U5.mjs → key-BQUnVMwc.mjs} +1 -1
  26. package/dist/{kv-cache-BVqMp1RC.cjs → kv-cache-CCEitzFw.cjs} +1 -1
  27. package/dist/{kv-cache-CKg5W012.js → kv-cache-DI4m-4xy.js} +1 -1
  28. package/dist/{ld-CN2nacLy.mjs → ld-CVbwQ8Fz.mjs} +2 -2
  29. package/dist/{middleware-CwIT91Nc.js → middleware-2Qp34eTb.js} +68 -8
  30. package/dist/{middleware-sbzAVAzo.mjs → middleware-BqkNe0c6.mjs} +1 -1
  31. package/dist/{middleware-DcmlYd2c.cjs → middleware-C7Afa66S.cjs} +1 -1
  32. package/dist/{middleware-DpEJSmjy.mjs → middleware-D3a1JsO1.mjs} +14 -11
  33. package/dist/{middleware-BXwn4gnl.cjs → middleware-Fcpx7tz6.cjs} +68 -8
  34. package/dist/{mod-43DJyETz.d.cts → mod-BtvLkCgb.d.cts} +1 -1
  35. package/dist/{mod-COgmn-UO.d.ts → mod-Du-UVCX_.d.ts} +1 -1
  36. package/dist/mod.cjs +4 -4
  37. package/dist/mod.d.cts +2 -2
  38. package/dist/mod.d.ts +2 -2
  39. package/dist/mod.js +4 -4
  40. package/dist/nodeinfo/handler.test.mjs +1 -1
  41. package/dist/{owner-CFgyZgkz.mjs → owner-D9CjMxWb.mjs} +2 -2
  42. package/dist/{proof-CpEH24hi.mjs → proof-DZWmoF6Z.mjs} +2 -2
  43. package/dist/{proof-ftbx50PI.js → proof-EY-uItWr.js} +1 -1
  44. package/dist/{proof-BTKH7fe9.cjs → proof-liMyPvsb.cjs} +1 -1
  45. package/dist/{send-pXXMu19o.mjs → send-IMhmEkun.mjs} +64 -6
  46. package/dist/sig/http.test.mjs +2 -2
  47. package/dist/sig/key.test.mjs +1 -1
  48. package/dist/sig/ld.test.mjs +2 -2
  49. package/dist/sig/mod.cjs +2 -2
  50. package/dist/sig/mod.js +2 -2
  51. package/dist/sig/owner.test.mjs +1 -1
  52. package/dist/sig/proof.test.mjs +1 -1
  53. package/dist/{temporal-B4rBDksp.mjs → temporal-BovRWwqL.mjs} +1 -1
  54. package/dist/utils/docloader.test.mjs +2 -2
  55. package/dist/utils/mod.cjs +1 -1
  56. package/dist/utils/mod.js +1 -1
  57. package/package.json +5 -5
@@ -2,10 +2,10 @@ import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  import { t as __exportAll } from "./chunk-CRNNMoPX.js";
4
4
  import { r as getDefaultActivityTransformers } from "./transformers-BGMIq1cs.js";
5
- import { c as validateCryptoKey, i as exportJwk, l as name, r as verifyRequest, s as importJwk, t as doubleKnock, u as version } from "./http-BP1pVF9m.js";
6
- import { _ as signJsonLd, a as doesActorOwnKey, c as assertSafeJsonLd, f as detachSignature, g as isInvalidUrlTypeError, h as isClearlyMalformedContextReference, m as hasSignature, n as signObject, o as getKeyOwner, p as getNormalizationContextLoader, r as verifyObject, s as InvalidContextReferenceError, u as compactJsonLd, v as verifyCompactJsonLd, x as wrapContextLoaderForJsonLd } from "./proof-ftbx50PI.js";
5
+ import { c as validateCryptoKey, i as exportJwk, l as name, r as verifyRequest, s as importJwk, t as doubleKnock, u as version } from "./http-Cx5dD1D_.js";
6
+ import { _ as signJsonLd, a as doesActorOwnKey, c as assertSafeJsonLd, f as detachSignature, g as isInvalidUrlTypeError, h as isClearlyMalformedContextReference, m as hasSignature, n as signObject, o as getKeyOwner, p as getNormalizationContextLoader, r as verifyObject, s as InvalidContextReferenceError, u as compactJsonLd, v as verifyCompactJsonLd, x as wrapContextLoaderForJsonLd } from "./proof-EY-uItWr.js";
7
7
  import { n as getNodeInfo, t as nodeInfoToJson } from "./types-DTONwNqL.js";
8
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-CKg5W012.js";
8
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-DI4m-4xy.js";
9
9
  import { getLogger, withContext } from "@logtape/logtape";
10
10
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
11
11
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
@@ -13,7 +13,7 @@ import { cloneDeep } from "es-toolkit";
13
13
  import { Router } from "uri-template-router";
14
14
  import { parseTemplate } from "url-template";
15
15
  import { encodeHex } from "byte-encodings/hex";
16
- import { getDocumentLoader } from "@fedify/vocab-runtime";
16
+ import { UrlError, getDocumentLoader, validatePublicUrl } from "@fedify/vocab-runtime";
17
17
  import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
18
18
  import jsonld from "@fedify/vocab-runtime/jsonld";
19
19
  import { lookupWebFinger } from "@fedify/webfinger";
@@ -2249,18 +2249,31 @@ async function readLimitedResponseBody(response, maxBytes) {
2249
2249
  if (truncated) result += "… (truncated)";
2250
2250
  return result;
2251
2251
  }
2252
- async function sendActivityInternal({ activity, activityId, keys, inbox, headers, specDeterminer, tracerProvider }, span) {
2252
+ async function sendActivityInternal({ activity, activityId, keys, inbox, allowPrivateAddress, headers, specDeterminer, tracerProvider }, span) {
2253
2253
  const logger = getLogger([
2254
2254
  "fedify",
2255
2255
  "federation",
2256
2256
  "outbox"
2257
2257
  ]);
2258
+ async function validateUrl(url) {
2259
+ if (!allowPrivateAddress) try {
2260
+ await validatePublicUrl(url);
2261
+ } catch (error) {
2262
+ if (error instanceof UrlError) logger.error("Disallowed private URL: {url}", {
2263
+ url,
2264
+ error
2265
+ });
2266
+ throw error;
2267
+ }
2268
+ }
2269
+ await validateUrl(inbox.href);
2258
2270
  headers = new Headers(headers);
2259
2271
  headers.set("Content-Type", "application/activity+json");
2260
2272
  const request = new Request(inbox, {
2261
2273
  method: "POST",
2262
2274
  headers,
2263
- body: JSON.stringify(activity)
2275
+ body: JSON.stringify(activity),
2276
+ redirect: "manual"
2264
2277
  });
2265
2278
  let rsaKey = null;
2266
2279
  for (const key of keys) if (key.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5") {
@@ -2276,9 +2289,10 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
2276
2289
  });
2277
2290
  let response;
2278
2291
  try {
2279
- response = rsaKey == null ? await fetch(request) : await doubleKnock(request, rsaKey, {
2292
+ response = rsaKey == null ? await fetchWithValidatedRedirects(request, validateUrl) : await doubleKnock(request, rsaKey, {
2280
2293
  tracerProvider,
2281
- specDeterminer
2294
+ specDeterminer,
2295
+ validateRedirect: validateUrl
2282
2296
  });
2283
2297
  } catch (error) {
2284
2298
  logger.error("Failed to send activity {activityId} to {inbox}:\n{error}", {
@@ -2310,6 +2324,49 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
2310
2324
  "activitypub.activity.id": activityId ?? ""
2311
2325
  });
2312
2326
  }
2327
+ async function fetchWithValidatedRedirects(request, validateUrl) {
2328
+ let body = await request.clone().text();
2329
+ for (let redirects = 0;; redirects++) {
2330
+ const response = await fetch(request, { redirect: "manual" });
2331
+ const location = response.headers.get("Location");
2332
+ if (![
2333
+ 301,
2334
+ 302,
2335
+ 303,
2336
+ 307,
2337
+ 308
2338
+ ].includes(response.status) || location == null) return response;
2339
+ await response.body?.cancel();
2340
+ if (redirects >= 20) throw new TypeError("Too many redirects");
2341
+ const url = new URL(location, request.url);
2342
+ await validateUrl(url.href);
2343
+ const headers = new Headers(request.headers);
2344
+ if (url.origin !== new URL(request.url).origin) {
2345
+ headers.delete("Authorization");
2346
+ headers.delete("Proxy-Authorization");
2347
+ headers.delete("Cookie");
2348
+ headers.delete("Host");
2349
+ }
2350
+ let method = request.method;
2351
+ if ((response.status === 301 || response.status === 302) && method === "POST" || response.status === 303 && method !== "GET" && method !== "HEAD") {
2352
+ method = "GET";
2353
+ body = void 0;
2354
+ for (const name of [
2355
+ "Content-Encoding",
2356
+ "Content-Language",
2357
+ "Content-Length",
2358
+ "Content-Location",
2359
+ "Content-Type"
2360
+ ]) headers.delete(name);
2361
+ }
2362
+ request = new Request(url, {
2363
+ method,
2364
+ headers,
2365
+ body,
2366
+ redirect: "manual"
2367
+ });
2368
+ }
2369
+ }
2313
2370
  /**
2314
2371
  * An error that is thrown when an activity fails to send to a remote inbox.
2315
2372
  * It contains structured information about the failure, including the HTTP
@@ -2815,6 +2872,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2815
2872
  }
2816
2873
  try {
2817
2874
  await sendActivity({
2875
+ allowPrivateAddress: this.allowPrivateAddress,
2818
2876
  keys,
2819
2877
  activity: message.activity,
2820
2878
  activityId: message.activityId,
@@ -3206,6 +3264,7 @@ var FederationImpl = class extends FederationBuilderImpl {
3206
3264
  });
3207
3265
  const promises = [];
3208
3266
  for (const inbox in inboxes) promises.push(sendActivity({
3267
+ allowPrivateAddress: this.allowPrivateAddress,
3209
3268
  keys,
3210
3269
  activity: jsonLd,
3211
3270
  activityId: activity.id?.href,
@@ -4346,6 +4405,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
4346
4405
  else logger.debug("Forwarding activity immediately without queue since queue is not set.");
4347
4406
  const promises = [];
4348
4407
  for (const inbox in inboxes) promises.push(sendActivity({
4408
+ allowPrivateAddress: this.federation.allowPrivateAddress,
4349
4409
  keys,
4350
4410
  activity: this.activity,
4351
4411
  activityId: this.activityId,
@@ -1,5 +1,5 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as FederationImpl } from "./middleware-DpEJSmjy.mjs";
4
+ import { n as FederationImpl } from "./middleware-D3a1JsO1.mjs";
5
5
  export { FederationImpl };
@@ -1,4 +1,4 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
- const require_middleware = require("./middleware-BXwn4gnl.cjs");
3
+ const require_middleware = require("./middleware-Fcpx7tz6.cjs");
4
4
  exports.FederationImpl = require_middleware.FederationImpl;
@@ -2,24 +2,24 @@ import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { n as RouterError } from "./router-CrMLXoOr.mjs";
5
- import { n as version, t as name } from "./deno-CGtm12Ft.mjs";
6
- import { a as validateCryptoKey, i as importJwk, t as exportJwk } from "./key-rC9mW1U5.mjs";
7
- import { l as verifyRequest } from "./http--P33qRwW.mjs";
8
- import { t as getAuthenticatedDocumentLoader } from "./docloader-_hXTUC-b.mjs";
5
+ import { n as version, t as name } from "./deno-D3gZ1DsB.mjs";
6
+ import { a as validateCryptoKey, i as importJwk, t as exportJwk } from "./key-BQUnVMwc.mjs";
7
+ import { l as verifyRequest } from "./http-Bn3-am6C.mjs";
8
+ import { t as getAuthenticatedDocumentLoader } from "./docloader-DIk3fEXZ.mjs";
9
9
  import { n as kvCache } from "./kv-cache-DqEKe5E0.mjs";
10
- import { a as compactJsonLd, c as getNormalizationContextLoader, d as isInvalidUrlTypeError, f as signJsonLd, g as wrapContextLoaderForJsonLd, l as hasSignature, p as verifyCompactJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as isClearlyMalformedContextReference } from "./ld-CN2nacLy.mjs";
11
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-CFgyZgkz.mjs";
12
- import { n as signObject, r as verifyObject } from "./proof-CpEH24hi.mjs";
10
+ import { a as compactJsonLd, c as getNormalizationContextLoader, d as isInvalidUrlTypeError, f as signJsonLd, g as wrapContextLoaderForJsonLd, l as hasSignature, p as verifyCompactJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as isClearlyMalformedContextReference } from "./ld-CVbwQ8Fz.mjs";
11
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-D9CjMxWb.mjs";
12
+ import { n as signObject, r as verifyObject } from "./proof-DZWmoF6Z.mjs";
13
13
  import { t as getNodeInfo } from "./client-HLLGHiTU.mjs";
14
14
  import { t as nodeInfoToJson } from "./types-C37hquWI.mjs";
15
- import { n as routeActivity } from "./inbox-BZNyUPzW.mjs";
16
- import { t as FederationBuilderImpl } from "./builder-DBKy92BX.mjs";
15
+ import { n as routeActivity } from "./inbox-DC8NbYIj.mjs";
16
+ import { t as FederationBuilderImpl } from "./builder-CAAXTNeK.mjs";
17
17
  import { t as buildCollectionSynchronizationHeader } from "./collection-ChgDTHLz.mjs";
18
18
  import { t as KvKeyCache } from "./keycache-DaQ3ndaJ.mjs";
19
19
  import { t as acceptsJsonLd } from "./negotiation-BehA2uul.mjs";
20
- import { t as hasMalformedKnownTemporalLiteral } from "./temporal-B4rBDksp.mjs";
20
+ import { t as hasMalformedKnownTemporalLiteral } from "./temporal-BovRWwqL.mjs";
21
21
  import { t as createExponentialBackoffPolicy } from "./retry-B_E3V_Dx.mjs";
22
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-pXXMu19o.mjs";
22
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-IMhmEkun.mjs";
23
23
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
24
24
  import { lookupWebFinger } from "@fedify/webfinger";
25
25
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
@@ -1656,6 +1656,7 @@ var FederationImpl = class extends FederationBuilderImpl {
1656
1656
  }
1657
1657
  try {
1658
1658
  await sendActivity({
1659
+ allowPrivateAddress: this.allowPrivateAddress,
1659
1660
  keys,
1660
1661
  activity: message.activity,
1661
1662
  activityId: message.activityId,
@@ -2047,6 +2048,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2047
2048
  });
2048
2049
  const promises = [];
2049
2050
  for (const inbox in inboxes) promises.push(sendActivity({
2051
+ allowPrivateAddress: this.allowPrivateAddress,
2050
2052
  keys,
2051
2053
  activity: jsonLd,
2052
2054
  activityId: activity.id?.href,
@@ -3187,6 +3189,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
3187
3189
  else logger.debug("Forwarding activity immediately without queue since queue is not set.");
3188
3190
  const promises = [];
3189
3191
  for (const inbox in inboxes) promises.push(sendActivity({
3192
+ allowPrivateAddress: this.federation.allowPrivateAddress,
3190
3193
  keys,
3191
3194
  activity: this.activity,
3192
3195
  activityId: this.activityId,
@@ -2,10 +2,10 @@ const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  const require_chunk = require("./chunk-DDcVe30Y.cjs");
4
4
  const require_transformers = require("./transformers-NeAONrAq.cjs");
5
- const require_http = require("./http-BuaGj55w.cjs");
6
- const require_proof = require("./proof-BTKH7fe9.cjs");
5
+ const require_http = require("./http-BLqv_3ue.cjs");
6
+ const require_proof = require("./proof-liMyPvsb.cjs");
7
7
  const require_types = require("./types-m8u9L86X.cjs");
8
- const require_kv_cache = require("./kv-cache-BVqMp1RC.cjs");
8
+ const require_kv_cache = require("./kv-cache-CCEitzFw.cjs");
9
9
  let _logtape_logtape = require("@logtape/logtape");
10
10
  let _fedify_vocab = require("@fedify/vocab");
11
11
  let _opentelemetry_api = require("@opentelemetry/api");
@@ -335,7 +335,7 @@ var FederationBuilderImpl = class {
335
335
  this.collectionTypeIds = {};
336
336
  }
337
337
  async build(options) {
338
- const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-DcmlYd2c.cjs"));
338
+ const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-C7Afa66S.cjs"));
339
339
  const f = new FederationImpl(options);
340
340
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
341
341
  f.router = this.router.clone();
@@ -2250,18 +2250,31 @@ async function readLimitedResponseBody(response, maxBytes) {
2250
2250
  if (truncated) result += "… (truncated)";
2251
2251
  return result;
2252
2252
  }
2253
- async function sendActivityInternal({ activity, activityId, keys, inbox, headers, specDeterminer, tracerProvider }, span) {
2253
+ async function sendActivityInternal({ activity, activityId, keys, inbox, allowPrivateAddress, headers, specDeterminer, tracerProvider }, span) {
2254
2254
  const logger = (0, _logtape_logtape.getLogger)([
2255
2255
  "fedify",
2256
2256
  "federation",
2257
2257
  "outbox"
2258
2258
  ]);
2259
+ async function validateUrl(url) {
2260
+ if (!allowPrivateAddress) try {
2261
+ await (0, _fedify_vocab_runtime.validatePublicUrl)(url);
2262
+ } catch (error) {
2263
+ if (error instanceof _fedify_vocab_runtime.UrlError) logger.error("Disallowed private URL: {url}", {
2264
+ url,
2265
+ error
2266
+ });
2267
+ throw error;
2268
+ }
2269
+ }
2270
+ await validateUrl(inbox.href);
2259
2271
  headers = new Headers(headers);
2260
2272
  headers.set("Content-Type", "application/activity+json");
2261
2273
  const request = new Request(inbox, {
2262
2274
  method: "POST",
2263
2275
  headers,
2264
- body: JSON.stringify(activity)
2276
+ body: JSON.stringify(activity),
2277
+ redirect: "manual"
2265
2278
  });
2266
2279
  let rsaKey = null;
2267
2280
  for (const key of keys) if (key.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5") {
@@ -2277,9 +2290,10 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
2277
2290
  });
2278
2291
  let response;
2279
2292
  try {
2280
- response = rsaKey == null ? await fetch(request) : await require_http.doubleKnock(request, rsaKey, {
2293
+ response = rsaKey == null ? await fetchWithValidatedRedirects(request, validateUrl) : await require_http.doubleKnock(request, rsaKey, {
2281
2294
  tracerProvider,
2282
- specDeterminer
2295
+ specDeterminer,
2296
+ validateRedirect: validateUrl
2283
2297
  });
2284
2298
  } catch (error) {
2285
2299
  logger.error("Failed to send activity {activityId} to {inbox}:\n{error}", {
@@ -2311,6 +2325,49 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
2311
2325
  "activitypub.activity.id": activityId ?? ""
2312
2326
  });
2313
2327
  }
2328
+ async function fetchWithValidatedRedirects(request, validateUrl) {
2329
+ let body = await request.clone().text();
2330
+ for (let redirects = 0;; redirects++) {
2331
+ const response = await fetch(request, { redirect: "manual" });
2332
+ const location = response.headers.get("Location");
2333
+ if (![
2334
+ 301,
2335
+ 302,
2336
+ 303,
2337
+ 307,
2338
+ 308
2339
+ ].includes(response.status) || location == null) return response;
2340
+ await response.body?.cancel();
2341
+ if (redirects >= 20) throw new TypeError("Too many redirects");
2342
+ const url = new URL(location, request.url);
2343
+ await validateUrl(url.href);
2344
+ const headers = new Headers(request.headers);
2345
+ if (url.origin !== new URL(request.url).origin) {
2346
+ headers.delete("Authorization");
2347
+ headers.delete("Proxy-Authorization");
2348
+ headers.delete("Cookie");
2349
+ headers.delete("Host");
2350
+ }
2351
+ let method = request.method;
2352
+ if ((response.status === 301 || response.status === 302) && method === "POST" || response.status === 303 && method !== "GET" && method !== "HEAD") {
2353
+ method = "GET";
2354
+ body = void 0;
2355
+ for (const name of [
2356
+ "Content-Encoding",
2357
+ "Content-Language",
2358
+ "Content-Length",
2359
+ "Content-Location",
2360
+ "Content-Type"
2361
+ ]) headers.delete(name);
2362
+ }
2363
+ request = new Request(url, {
2364
+ method,
2365
+ headers,
2366
+ body,
2367
+ redirect: "manual"
2368
+ });
2369
+ }
2370
+ }
2314
2371
  /**
2315
2372
  * An error that is thrown when an activity fails to send to a remote inbox.
2316
2373
  * It contains structured information about the failure, including the HTTP
@@ -2809,6 +2866,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2809
2866
  }
2810
2867
  try {
2811
2868
  await sendActivity({
2869
+ allowPrivateAddress: this.allowPrivateAddress,
2812
2870
  keys,
2813
2871
  activity: message.activity,
2814
2872
  activityId: message.activityId,
@@ -3200,6 +3258,7 @@ var FederationImpl = class extends FederationBuilderImpl {
3200
3258
  });
3201
3259
  const promises = [];
3202
3260
  for (const inbox in inboxes) promises.push(sendActivity({
3261
+ allowPrivateAddress: this.allowPrivateAddress,
3203
3262
  keys,
3204
3263
  activity: jsonLd,
3205
3264
  activityId: activity.id?.href,
@@ -4340,6 +4399,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
4340
4399
  else logger.debug("Forwarding activity immediately without queue since queue is not set.");
4341
4400
  const promises = [];
4342
4401
  for (const inbox in inboxes) promises.push(sendActivity({
4402
+ allowPrivateAddress: this.federation.allowPrivateAddress,
4343
4403
  keys,
4344
4404
  activity: this.activity,
4345
4405
  activityId: this.activityId,
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { X as ActorDispatcher, Y as ActorAliasMapper, Z as ActorHandleMapper, mt as WebFingerLinksDispatcher, s as RequestContext } from "./context-CJZHWLmz.cjs";
2
+ import { X as ActorDispatcher, Y as ActorAliasMapper, Z as ActorHandleMapper, mt as WebFingerLinksDispatcher, s as RequestContext } from "./context-zLLwVY_G.cjs";
3
3
  import { Span, Tracer } from "@opentelemetry/api";
4
4
 
5
5
  //#region src/federation/webfinger.d.ts
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { X as ActorDispatcher, Y as ActorAliasMapper, Z as ActorHandleMapper, mt as WebFingerLinksDispatcher, s as RequestContext } from "./context-DnsFj3yK.js";
2
+ import { X as ActorDispatcher, Y as ActorAliasMapper, Z as ActorHandleMapper, mt as WebFingerLinksDispatcher, s as RequestContext } from "./context-DJ5oMnte.js";
3
3
  import { Span, Tracer } from "@opentelemetry/api";
4
4
 
5
5
  //#region src/federation/webfinger.d.ts
package/dist/mod.cjs CHANGED
@@ -4,11 +4,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  require("./chunk-DDcVe30Y.cjs");
5
5
  const require_transformers = require("./transformers-NeAONrAq.cjs");
6
6
  require("./compat/mod.cjs");
7
- const require_http = require("./http-BuaGj55w.cjs");
8
- const require_middleware = require("./middleware-BXwn4gnl.cjs");
9
- const require_proof = require("./proof-BTKH7fe9.cjs");
7
+ const require_http = require("./http-BLqv_3ue.cjs");
8
+ const require_middleware = require("./middleware-Fcpx7tz6.cjs");
9
+ const require_proof = require("./proof-liMyPvsb.cjs");
10
10
  const require_types = require("./types-m8u9L86X.cjs");
11
- const require_kv_cache = require("./kv-cache-BVqMp1RC.cjs");
11
+ const require_kv_cache = require("./kv-cache-CCEitzFw.cjs");
12
12
  const require_federation_mod = require("./federation/mod.cjs");
13
13
  require("./nodeinfo/mod.cjs");
14
14
  require("./runtime/mod.cjs");
package/dist/mod.d.cts CHANGED
@@ -2,10 +2,10 @@
2
2
  import { a as InboundService, c as OutboundService, d as Software, f as Usage, i as parseNodeInfo, l as Protocol, n as ParseNodeInfoOptions, o as JsonValue, p as nodeInfoToJson, r as getNodeInfo, s as NodeInfo, t as GetNodeInfoOptions, u as Services } from "./client-CAM_bQXx.cjs";
3
3
  import { a as signRequest, c as FetchKeyResult, d as fetchKey, f as generateCryptoKeyPair, i as VerifyRequestOptions, l as KeyCache, n as HttpMessageSignaturesSpecDeterminer, o as verifyRequest, p as importJwk, r as SignRequestOptions, s as FetchKeyOptions, t as HttpMessageSignaturesSpec, u as exportJwk } from "./http-RYvZHWMc.cjs";
4
4
  import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "./owner-DEvZuyOE.cjs";
5
- import { $ as AuthorizePredicate, A as CreateExponentialBackoffPolicyOptions, B as RespondWithObjectOptions, C as InboxListenerSetters, D as FederationOrigin, E as FederationKvPrefixes, F as createFederationBuilder, G as MessageQueue, H as respondWithObjectIfAcceptable, I as Router, J as ParallelMessageQueue, K as MessageQueueEnqueueOptions, L as RouterError, M as RetryPolicy, N as createExponentialBackoffPolicy, O as FederationQueueOptions, P as Message, Q as ActorKeyPairsDispatcher, R as RouterOptions, S as IdempotencyStrategy, T as Rfc6570Expression, U as InProcessMessageQueue, V as respondWithObject, W as InProcessMessageQueueOptions, X as ActorDispatcher, Y as ActorAliasMapper, Z as ActorHandleMapper, _ as FederationBuilder, _t as PageItems, a as InboxContext, at as CustomCollectionDispatcher, b as FederationStartQueueOptions, bt as ActivityTransformer, c as RouteActivityOptions, ct as NodeInfoDispatcher, d as ActorCallbackSetters, dt as OutboxErrorHandler, et as CollectionCounter, f as CollectionCallbackSetters, ft as OutboxPermanentFailureHandler, g as Federation, gt as SenderKeyPair, h as Federatable, ht as SendActivityError, i as GetSignedKeyOptions, it as CustomCollectionCursor, j as RetryContext, k as createFederation, l as SendActivityOptions, lt as ObjectAuthorizePredicate, m as CustomCollectionCallbackSetters, mt as WebFingerLinksDispatcher, n as Context, nt as CollectionDispatcher, o as ParseUriResult, ot as InboxErrorHandler, p as ConstructorWithTypeId, pt as SharedInboxKeyDispatcher, q as MessageQueueListenOptions, r as ForwardActivityOptions, rt as CustomCollectionCounter, s as RequestContext, st as InboxListener, t as ActorKeyPair, tt as CollectionCursor, u as SendActivityOptionsForCollection, ut as ObjectDispatcher, v as FederationFetchOptions, vt as buildCollectionSynchronizationHeader, w as ObjectCallbackSetters, x as IdempotencyKeyCallback, y as FederationOptions, yt as digest, z as RouterRouteResult } from "./context-CJZHWLmz.cjs";
5
+ import { $ as AuthorizePredicate, A as CreateExponentialBackoffPolicyOptions, B as RespondWithObjectOptions, C as InboxListenerSetters, D as FederationOrigin, E as FederationKvPrefixes, F as createFederationBuilder, G as MessageQueue, H as respondWithObjectIfAcceptable, I as Router, J as ParallelMessageQueue, K as MessageQueueEnqueueOptions, L as RouterError, M as RetryPolicy, N as createExponentialBackoffPolicy, O as FederationQueueOptions, P as Message, Q as ActorKeyPairsDispatcher, R as RouterOptions, S as IdempotencyStrategy, T as Rfc6570Expression, U as InProcessMessageQueue, V as respondWithObject, W as InProcessMessageQueueOptions, X as ActorDispatcher, Y as ActorAliasMapper, Z as ActorHandleMapper, _ as FederationBuilder, _t as PageItems, a as InboxContext, at as CustomCollectionDispatcher, b as FederationStartQueueOptions, bt as ActivityTransformer, c as RouteActivityOptions, ct as NodeInfoDispatcher, d as ActorCallbackSetters, dt as OutboxErrorHandler, et as CollectionCounter, f as CollectionCallbackSetters, ft as OutboxPermanentFailureHandler, g as Federation, gt as SenderKeyPair, h as Federatable, ht as SendActivityError, i as GetSignedKeyOptions, it as CustomCollectionCursor, j as RetryContext, k as createFederation, l as SendActivityOptions, lt as ObjectAuthorizePredicate, m as CustomCollectionCallbackSetters, mt as WebFingerLinksDispatcher, n as Context, nt as CollectionDispatcher, o as ParseUriResult, ot as InboxErrorHandler, p as ConstructorWithTypeId, pt as SharedInboxKeyDispatcher, q as MessageQueueListenOptions, r as ForwardActivityOptions, rt as CustomCollectionCounter, s as RequestContext, st as InboxListener, t as ActorKeyPair, tt as CollectionCursor, u as SendActivityOptionsForCollection, ut as ObjectDispatcher, v as FederationFetchOptions, vt as buildCollectionSynchronizationHeader, w as ObjectCallbackSetters, x as IdempotencyKeyCallback, y as FederationOptions, yt as digest, z as RouterRouteResult } from "./context-zLLwVY_G.cjs";
6
6
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "./kv-gJ8LYbxX.cjs";
7
7
  import { actorDehydrator, autoIdAssigner, getDefaultActivityTransformers } from "./compat/mod.cjs";
8
- import { n as handleWebFinger, t as WebFingerHandlerParameters } from "./mod-43DJyETz.cjs";
8
+ import { n as handleWebFinger, t as WebFingerHandlerParameters } from "./mod-BtvLkCgb.cjs";
9
9
  import { _ as verifyJsonLd, a as createProof, c as verifyProof, d as VerifyJsonLdOptions, f as VerifySignatureOptions, g as signJsonLd, h as detachSignature, i as VerifyProofOptions, l as CreateSignatureOptions, m as createSignature, n as SignObjectOptions, o as signObject, p as attachSignature, r as VerifyObjectOptions, s as verifyObject, t as CreateProofOptions, u as SignJsonLdOptions, v as verifySignature } from "./mod-CB6pc2pw.cjs";
10
10
  import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./mod-B2zB0rDg.cjs";
11
11
  export * from "@fedify/vocab-runtime";
package/dist/mod.d.ts CHANGED
@@ -2,10 +2,10 @@
2
2
  import { a as InboundService, c as OutboundService, d as Software, f as Usage, i as parseNodeInfo, l as Protocol, n as ParseNodeInfoOptions, o as JsonValue, p as nodeInfoToJson, r as getNodeInfo, s as NodeInfo, t as GetNodeInfoOptions, u as Services } from "./client-CSddvgWN.js";
3
3
  import { a as signRequest, c as FetchKeyResult, d as fetchKey, f as generateCryptoKeyPair, i as VerifyRequestOptions, l as KeyCache, n as HttpMessageSignaturesSpecDeterminer, o as verifyRequest, p as importJwk, r as SignRequestOptions, s as FetchKeyOptions, t as HttpMessageSignaturesSpec, u as exportJwk } from "./http-C4D0ajx0.js";
4
4
  import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "./owner-CnngXDNJ.js";
5
- import { $ as AuthorizePredicate, A as CreateExponentialBackoffPolicyOptions, B as RespondWithObjectOptions, C as InboxListenerSetters, D as FederationOrigin, E as FederationKvPrefixes, F as createFederationBuilder, G as MessageQueue, H as respondWithObjectIfAcceptable, I as Router, J as ParallelMessageQueue, K as MessageQueueEnqueueOptions, L as RouterError, M as RetryPolicy, N as createExponentialBackoffPolicy, O as FederationQueueOptions, P as Message, Q as ActorKeyPairsDispatcher, R as RouterOptions, S as IdempotencyStrategy, T as Rfc6570Expression, U as InProcessMessageQueue, V as respondWithObject, W as InProcessMessageQueueOptions, X as ActorDispatcher, Y as ActorAliasMapper, Z as ActorHandleMapper, _ as FederationBuilder, _t as PageItems, a as InboxContext, at as CustomCollectionDispatcher, b as FederationStartQueueOptions, bt as ActivityTransformer, c as RouteActivityOptions, ct as NodeInfoDispatcher, d as ActorCallbackSetters, dt as OutboxErrorHandler, et as CollectionCounter, f as CollectionCallbackSetters, ft as OutboxPermanentFailureHandler, g as Federation, gt as SenderKeyPair, h as Federatable, ht as SendActivityError, i as GetSignedKeyOptions, it as CustomCollectionCursor, j as RetryContext, k as createFederation, l as SendActivityOptions, lt as ObjectAuthorizePredicate, m as CustomCollectionCallbackSetters, mt as WebFingerLinksDispatcher, n as Context, nt as CollectionDispatcher, o as ParseUriResult, ot as InboxErrorHandler, p as ConstructorWithTypeId, pt as SharedInboxKeyDispatcher, q as MessageQueueListenOptions, r as ForwardActivityOptions, rt as CustomCollectionCounter, s as RequestContext, st as InboxListener, t as ActorKeyPair, tt as CollectionCursor, u as SendActivityOptionsForCollection, ut as ObjectDispatcher, v as FederationFetchOptions, vt as buildCollectionSynchronizationHeader, w as ObjectCallbackSetters, x as IdempotencyKeyCallback, y as FederationOptions, yt as digest, z as RouterRouteResult } from "./context-DnsFj3yK.js";
5
+ import { $ as AuthorizePredicate, A as CreateExponentialBackoffPolicyOptions, B as RespondWithObjectOptions, C as InboxListenerSetters, D as FederationOrigin, E as FederationKvPrefixes, F as createFederationBuilder, G as MessageQueue, H as respondWithObjectIfAcceptable, I as Router, J as ParallelMessageQueue, K as MessageQueueEnqueueOptions, L as RouterError, M as RetryPolicy, N as createExponentialBackoffPolicy, O as FederationQueueOptions, P as Message, Q as ActorKeyPairsDispatcher, R as RouterOptions, S as IdempotencyStrategy, T as Rfc6570Expression, U as InProcessMessageQueue, V as respondWithObject, W as InProcessMessageQueueOptions, X as ActorDispatcher, Y as ActorAliasMapper, Z as ActorHandleMapper, _ as FederationBuilder, _t as PageItems, a as InboxContext, at as CustomCollectionDispatcher, b as FederationStartQueueOptions, bt as ActivityTransformer, c as RouteActivityOptions, ct as NodeInfoDispatcher, d as ActorCallbackSetters, dt as OutboxErrorHandler, et as CollectionCounter, f as CollectionCallbackSetters, ft as OutboxPermanentFailureHandler, g as Federation, gt as SenderKeyPair, h as Federatable, ht as SendActivityError, i as GetSignedKeyOptions, it as CustomCollectionCursor, j as RetryContext, k as createFederation, l as SendActivityOptions, lt as ObjectAuthorizePredicate, m as CustomCollectionCallbackSetters, mt as WebFingerLinksDispatcher, n as Context, nt as CollectionDispatcher, o as ParseUriResult, ot as InboxErrorHandler, p as ConstructorWithTypeId, pt as SharedInboxKeyDispatcher, q as MessageQueueListenOptions, r as ForwardActivityOptions, rt as CustomCollectionCounter, s as RequestContext, st as InboxListener, t as ActorKeyPair, tt as CollectionCursor, u as SendActivityOptionsForCollection, ut as ObjectDispatcher, v as FederationFetchOptions, vt as buildCollectionSynchronizationHeader, w as ObjectCallbackSetters, x as IdempotencyKeyCallback, y as FederationOptions, yt as digest, z as RouterRouteResult } from "./context-DJ5oMnte.js";
6
6
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "./kv-D6hNiMTK.js";
7
7
  import { actorDehydrator, autoIdAssigner, getDefaultActivityTransformers } from "./compat/mod.js";
8
- import { n as handleWebFinger, t as WebFingerHandlerParameters } from "./mod-COgmn-UO.js";
8
+ import { n as handleWebFinger, t as WebFingerHandlerParameters } from "./mod-Du-UVCX_.js";
9
9
  import { _ as verifyJsonLd, a as createProof, c as verifyProof, d as VerifyJsonLdOptions, f as VerifySignatureOptions, g as signJsonLd, h as detachSignature, i as VerifyProofOptions, l as CreateSignatureOptions, m as createSignature, n as SignObjectOptions, o as signObject, p as attachSignature, r as VerifyObjectOptions, s as verifyObject, t as CreateProofOptions, u as SignJsonLdOptions, v as verifySignature } from "./mod-CiQNNAQL.js";
10
10
  import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./mod-CD1youdZ.js";
11
11
  export * from "@fedify/vocab-runtime";
package/dist/mod.js CHANGED
@@ -3,11 +3,11 @@ import { URLPattern } from "urlpattern-polyfill";
3
3
  import "./chunk-CRNNMoPX.js";
4
4
  import { n as autoIdAssigner, r as getDefaultActivityTransformers, t as actorDehydrator } from "./transformers-BGMIq1cs.js";
5
5
  import "./compat/mod.js";
6
- import { a as fetchKey, i as exportJwk, n as signRequest, o as generateCryptoKeyPair, r as verifyRequest, s as importJwk } from "./http-BP1pVF9m.js";
7
- import { a as createExponentialBackoffPolicy, c as buildCollectionSynchronizationHeader, d as Router, f as RouterError, i as SendActivityError, l as digest, o as respondWithObject, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as createFederationBuilder } from "./middleware-CwIT91Nc.js";
8
- import { _ as signJsonLd, a as doesActorOwnKey, b as verifySignature, d as createSignature, f as detachSignature, i as verifyProof, l as attachSignature, n as signObject, o as getKeyOwner, r as verifyObject, t as createProof, y as verifyJsonLd } from "./proof-ftbx50PI.js";
6
+ import { a as fetchKey, i as exportJwk, n as signRequest, o as generateCryptoKeyPair, r as verifyRequest, s as importJwk } from "./http-Cx5dD1D_.js";
7
+ import { a as createExponentialBackoffPolicy, c as buildCollectionSynchronizationHeader, d as Router, f as RouterError, i as SendActivityError, l as digest, o as respondWithObject, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as createFederationBuilder } from "./middleware-2Qp34eTb.js";
8
+ import { _ as signJsonLd, a as doesActorOwnKey, b as verifySignature, d as createSignature, f as detachSignature, i as verifyProof, l as attachSignature, n as signObject, o as getKeyOwner, r as verifyObject, t as createProof, y as verifyJsonLd } from "./proof-EY-uItWr.js";
9
9
  import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "./types-DTONwNqL.js";
10
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-CKg5W012.js";
10
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-DI4m-4xy.js";
11
11
  import { InProcessMessageQueue, MemoryKvStore, ParallelMessageQueue } from "./federation/mod.js";
12
12
  import "./nodeinfo/mod.js";
13
13
  import "./runtime/mod.js";
@@ -5,7 +5,7 @@ import { n as createRequestContext } from "../context-Juj6bdHC.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
6
  import "../std__assert-Duiq_YC9.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-BrZHNugx.mjs";
8
- import { a as createFederation, h as handleNodeInfoJrd, m as handleNodeInfo } from "../middleware-DpEJSmjy.mjs";
8
+ import { a as createFederation, h as handleNodeInfoJrd, m as handleNodeInfo } from "../middleware-D3a1JsO1.mjs";
9
9
  import { test } from "@fedify/fixture";
10
10
  //#region src/nodeinfo/handler.test.ts
11
11
  test("handleNodeInfo()", async () => {
@@ -1,8 +1,8 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-CGtm12Ft.mjs";
5
- import "./key-rC9mW1U5.mjs";
4
+ import { n as version, t as name } from "./deno-D3gZ1DsB.mjs";
5
+ import "./key-BQUnVMwc.mjs";
6
6
  import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
7
7
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
8
8
  import { getDocumentLoader } from "@fedify/vocab-runtime";
@@ -1,8 +1,8 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-CGtm12Ft.mjs";
5
- import { a as validateCryptoKey, n as fetchKey } from "./key-rC9mW1U5.mjs";
4
+ import { n as version, t as name } from "./deno-D3gZ1DsB.mjs";
5
+ import { a as validateCryptoKey, n as fetchKey } from "./key-BQUnVMwc.mjs";
6
6
  import { Activity, DataIntegrityProof, Multikey, getTypeId } from "@fedify/vocab";
7
7
  import { SpanStatusCode, trace } from "@opentelemetry/api";
8
8
  import { getLogger } from "@logtape/logtape";
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { a as fetchKey, c as validateCryptoKey, l as name, u as version } from "./http-BP1pVF9m.js";
3
+ import { a as fetchKey, c as validateCryptoKey, l as name, u as version } from "./http-Cx5dD1D_.js";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, getTypeId, isActor } from "@fedify/vocab";
6
6
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
@@ -1,7 +1,7 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  const require_chunk = require("./chunk-DDcVe30Y.cjs");
4
- const require_http = require("./http-BuaGj55w.cjs");
4
+ const require_http = require("./http-BLqv_3ue.cjs");
5
5
  let _logtape_logtape = require("@logtape/logtape");
6
6
  let _fedify_vocab = require("@fedify/vocab");
7
7
  let _opentelemetry_api = require("@opentelemetry/api");
@@ -1,9 +1,10 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-CGtm12Ft.mjs";
5
- import { n as doubleKnock } from "./http--P33qRwW.mjs";
4
+ import { n as version, t as name } from "./deno-D3gZ1DsB.mjs";
5
+ import { n as doubleKnock } from "./http-Bn3-am6C.mjs";
6
6
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
7
+ import { UrlError, validatePublicUrl } from "@fedify/vocab-runtime";
7
8
  import { getLogger } from "@logtape/logtape";
8
9
  //#region src/federation/send.ts
9
10
  /**
@@ -91,18 +92,31 @@ async function readLimitedResponseBody(response, maxBytes) {
91
92
  if (truncated) result += "… (truncated)";
92
93
  return result;
93
94
  }
94
- async function sendActivityInternal({ activity, activityId, keys, inbox, headers, specDeterminer, tracerProvider }, span) {
95
+ async function sendActivityInternal({ activity, activityId, keys, inbox, allowPrivateAddress, headers, specDeterminer, tracerProvider }, span) {
95
96
  const logger = getLogger([
96
97
  "fedify",
97
98
  "federation",
98
99
  "outbox"
99
100
  ]);
101
+ async function validateUrl(url) {
102
+ if (!allowPrivateAddress) try {
103
+ await validatePublicUrl(url);
104
+ } catch (error) {
105
+ if (error instanceof UrlError) logger.error("Disallowed private URL: {url}", {
106
+ url,
107
+ error
108
+ });
109
+ throw error;
110
+ }
111
+ }
112
+ await validateUrl(inbox.href);
100
113
  headers = new Headers(headers);
101
114
  headers.set("Content-Type", "application/activity+json");
102
115
  const request = new Request(inbox, {
103
116
  method: "POST",
104
117
  headers,
105
- body: JSON.stringify(activity)
118
+ body: JSON.stringify(activity),
119
+ redirect: "manual"
106
120
  });
107
121
  let rsaKey = null;
108
122
  for (const key of keys) if (key.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5") {
@@ -118,9 +132,10 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
118
132
  });
119
133
  let response;
120
134
  try {
121
- response = rsaKey == null ? await fetch(request) : await doubleKnock(request, rsaKey, {
135
+ response = rsaKey == null ? await fetchWithValidatedRedirects(request, validateUrl) : await doubleKnock(request, rsaKey, {
122
136
  tracerProvider,
123
- specDeterminer
137
+ specDeterminer,
138
+ validateRedirect: validateUrl
124
139
  });
125
140
  } catch (error) {
126
141
  logger.error("Failed to send activity {activityId} to {inbox}:\n{error}", {
@@ -152,6 +167,49 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
152
167
  "activitypub.activity.id": activityId ?? ""
153
168
  });
154
169
  }
170
+ async function fetchWithValidatedRedirects(request, validateUrl) {
171
+ let body = await request.clone().text();
172
+ for (let redirects = 0;; redirects++) {
173
+ const response = await fetch(request, { redirect: "manual" });
174
+ const location = response.headers.get("Location");
175
+ if (![
176
+ 301,
177
+ 302,
178
+ 303,
179
+ 307,
180
+ 308
181
+ ].includes(response.status) || location == null) return response;
182
+ await response.body?.cancel();
183
+ if (redirects >= 20) throw new TypeError("Too many redirects");
184
+ const url = new URL(location, request.url);
185
+ await validateUrl(url.href);
186
+ const headers = new Headers(request.headers);
187
+ if (url.origin !== new URL(request.url).origin) {
188
+ headers.delete("Authorization");
189
+ headers.delete("Proxy-Authorization");
190
+ headers.delete("Cookie");
191
+ headers.delete("Host");
192
+ }
193
+ let method = request.method;
194
+ if ((response.status === 301 || response.status === 302) && method === "POST" || response.status === 303 && method !== "GET" && method !== "HEAD") {
195
+ method = "GET";
196
+ body = void 0;
197
+ for (const name of [
198
+ "Content-Encoding",
199
+ "Content-Language",
200
+ "Content-Length",
201
+ "Content-Location",
202
+ "Content-Type"
203
+ ]) headers.delete(name);
204
+ }
205
+ request = new Request(url, {
206
+ method,
207
+ headers,
208
+ body,
209
+ redirect: "manual"
210
+ });
211
+ }
212
+ }
155
213
  /**
156
214
  * An error that is thrown when an activity fails to send to a remote inbox.
157
215
  * It contains structured information about the failure, including the HTTP
@@ -7,8 +7,8 @@ import { a as assertExists, t as assertStringIncludes } from "../std__assert-Dui
7
7
  import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
8
8
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
9
9
  import { t as assert } from "../assert-ddO5KLpe.mjs";
10
- import { t as exportJwk } from "../key-rC9mW1U5.mjs";
11
- import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase } from "../http--P33qRwW.mjs";
10
+ import { t as exportJwk } from "../key-BQUnVMwc.mjs";
11
+ import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase } from "../http-Bn3-am6C.mjs";
12
12
  import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-CtZLJq76.mjs";
13
13
  import { mockDocumentLoader, test } from "@fedify/fixture";
14
14
  import { FetchError, exportSpki } from "@fedify/vocab-runtime";