@fedify/fedify 2.2.6 → 2.2.8

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 (52) hide show
  1. package/README.md +5 -4
  2. package/dist/{builder-C-al99Vs.mjs → builder-Hr1c39Ha.mjs} +4 -2
  3. package/dist/{client-D_1QpnWt.mjs → client-dx126nMS.mjs} +63 -5
  4. package/dist/compat/transformers.test.mjs +1 -1
  5. package/dist/{deno-B0LcALOm.mjs → deno-B_vGx2Ji.mjs} +1 -1
  6. package/dist/{docloader-DLAjdiZt.mjs → docloader-DixiMoIZ.mjs} +2 -2
  7. package/dist/federation/builder.test.mjs +13 -1
  8. package/dist/federation/handler.test.mjs +3 -3
  9. package/dist/federation/idempotency.test.mjs +2 -2
  10. package/dist/federation/middleware.test.mjs +6 -6
  11. package/dist/federation/mod.cjs +1 -1
  12. package/dist/federation/mod.js +1 -1
  13. package/dist/federation/send.test.mjs +3 -3
  14. package/dist/federation/temporal.test.mjs +1 -1
  15. package/dist/federation/webfinger.test.mjs +69 -7
  16. package/dist/{http-BkivuOe4.mjs → http-BlHW6_Oi.mjs} +2 -2
  17. package/dist/{http-C-9duWvR.js → http-C-FdpmAl.js} +1 -1
  18. package/dist/{http-NEN2KDMb.cjs → http-DLRpF855.cjs} +1 -1
  19. package/dist/{key-BcpJR7wT.mjs → key-6U1u5H_H.mjs} +1 -1
  20. package/dist/{kv-cache-8o7zAqEi.js → kv-cache-BjlL4Zk0.js} +1 -1
  21. package/dist/{kv-cache-9K6uVGgd.cjs → kv-cache-DKprbYof.cjs} +1 -1
  22. package/dist/{ld-DAZQsoKN.mjs → ld-DDBxn1rq.mjs} +2 -2
  23. package/dist/{middleware-C3JAusAj.mjs → middleware-BJM6vrlT.mjs} +46 -29
  24. package/dist/{middleware-BUiHyCQ9.cjs → middleware-Bj5UFOaT.cjs} +42 -23
  25. package/dist/{middleware-CeqmkLh1.cjs → middleware-DNJYfRV4.cjs} +1 -1
  26. package/dist/{middleware-Bk-ge16h.js → middleware-DOkcTiZ-.js} +41 -22
  27. package/dist/{middleware-BysI6Pqz.mjs → middleware-Ds3ujCKo.mjs} +1 -1
  28. package/dist/mod.cjs +5 -5
  29. package/dist/mod.js +5 -5
  30. package/dist/nodeinfo/client.test.mjs +61 -1
  31. package/dist/nodeinfo/handler.test.mjs +1 -1
  32. package/dist/nodeinfo/mod.cjs +1 -1
  33. package/dist/nodeinfo/mod.js +1 -1
  34. package/dist/{owner-CwVIBwY0.mjs → owner-vuyMTd_f.mjs} +2 -2
  35. package/dist/{proof-wrxzZi_u.mjs → proof-BGrdGhcb.mjs} +2 -2
  36. package/dist/{proof-C2en2Cmb.cjs → proof-BNGY2IU6.cjs} +1 -1
  37. package/dist/{proof-IyDe0jjt.js → proof-DA_wkPds.js} +1 -1
  38. package/dist/{send-DOlXF7S8.mjs → send-BvazsIXC.mjs} +2 -2
  39. package/dist/sig/http.test.mjs +2 -2
  40. package/dist/sig/key.test.mjs +1 -1
  41. package/dist/sig/ld.test.mjs +2 -2
  42. package/dist/sig/mod.cjs +2 -2
  43. package/dist/sig/mod.js +2 -2
  44. package/dist/sig/owner.test.mjs +1 -1
  45. package/dist/sig/proof.test.mjs +1 -1
  46. package/dist/{temporal-B13wkvUP.mjs → temporal-MdUFasAg.mjs} +1 -1
  47. package/dist/{types-CAY3OdLq.js → types-DTONwNqL.js} +63 -5
  48. package/dist/{types-KC4QAoxe.cjs → types-m8u9L86X.cjs} +62 -4
  49. package/dist/utils/docloader.test.mjs +2 -2
  50. package/dist/utils/mod.cjs +1 -1
  51. package/dist/utils/mod.js +1 -1
  52. package/package.json +6 -6
@@ -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-NEN2KDMb.cjs");
6
- const require_proof = require("./proof-C2en2Cmb.cjs");
7
- const require_types = require("./types-KC4QAoxe.cjs");
8
- const require_kv_cache = require("./kv-cache-9K6uVGgd.cjs");
5
+ const require_http = require("./http-DLRpF855.cjs");
6
+ const require_proof = require("./proof-BNGY2IU6.cjs");
7
+ const require_types = require("./types-m8u9L86X.cjs");
8
+ const require_kv_cache = require("./kv-cache-DKprbYof.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");
@@ -212,7 +212,7 @@ var FederationBuilderImpl = class {
212
212
  this.collectionTypeIds = {};
213
213
  }
214
214
  async build(options) {
215
- const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-CeqmkLh1.cjs"));
215
+ const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-DNJYfRV4.cjs"));
216
216
  const f = new FederationImpl(options);
217
217
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
218
218
  f.router = this.router.clone();
@@ -223,6 +223,8 @@ var FederationBuilderImpl = class {
223
223
  f.webFingerLinksDispatcher = this.webFingerLinksDispatcher;
224
224
  f.objectCallbacks = { ...this.objectCallbacks };
225
225
  f.objectTypeIds = { ...this.objectTypeIds };
226
+ f.collectionCallbacks = { ...this.collectionCallbacks };
227
+ f.collectionTypeIds = { ...this.collectionTypeIds };
226
228
  f.inboxPath = this.inboxPath;
227
229
  f.outboxPath = this.outboxPath;
228
230
  f.inboxCallbacks = this.inboxCallbacks == null ? void 0 : { ...this.inboxCallbacks };
@@ -2808,6 +2810,24 @@ const logger = (0, _logtape_logtape.getLogger)([
2808
2810
  "webfinger",
2809
2811
  "server"
2810
2812
  ]);
2813
+ function getWebFingerSubjectAndAliases({ resourceUrl, actorUri, preferredUsername, acctUsername, host, contextHost }) {
2814
+ const aliases = [];
2815
+ let subject = resourceUrl.href;
2816
+ if (resourceUrl.protocol != "acct:" && preferredUsername != null) {
2817
+ aliases.push(`acct:${preferredUsername}@${host ?? contextHost}`);
2818
+ if (host != null && host !== contextHost) aliases.push(`acct:${preferredUsername}@${contextHost}`);
2819
+ }
2820
+ if (resourceUrl.href !== actorUri.href) aliases.push(actorUri.href);
2821
+ if (resourceUrl.protocol === "acct:" && host != null && host !== contextHost && !resourceUrl.href.endsWith(`@${host}`)) {
2822
+ subject = `acct:${preferredUsername ?? acctUsername}@${host}`;
2823
+ aliases.push(resourceUrl.href);
2824
+ if (preferredUsername != null && preferredUsername !== "" && preferredUsername !== acctUsername) aliases.push(`acct:${preferredUsername}@${contextHost}`);
2825
+ }
2826
+ return {
2827
+ subject,
2828
+ aliases
2829
+ };
2830
+ }
2811
2831
  /**
2812
2832
  * Handles a WebFinger request. You would not typically call this function
2813
2833
  * directly, but instead use {@link Federation.fetch} method.
@@ -2862,6 +2882,7 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
2862
2882
  return identifier;
2863
2883
  }
2864
2884
  let identifier = null;
2885
+ let acctUsername = null;
2865
2886
  const uriParsed = context.parseUri(resourceUrl);
2866
2887
  if (uriParsed?.type != "actor") {
2867
2888
  const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
@@ -2875,8 +2896,9 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
2875
2896
  const normalizedHost = portMatch == null ? (0, node_url.domainToASCII)(match[2].toLowerCase()) : (0, node_url.domainToASCII)(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
2876
2897
  if (normalizedHost != context.url.host && normalizedHost != host) return await onNotFound(request);
2877
2898
  else {
2878
- identifier = await mapUsernameToIdentifier(match[1]);
2879
- resourceUrl = new URL(`acct:${match[1]}@${normalizedHost}`);
2899
+ acctUsername = match[1];
2900
+ identifier = await mapUsernameToIdentifier(acctUsername);
2901
+ resourceUrl = new URL(`acct:${acctUsername}@${normalizedHost}`);
2880
2902
  }
2881
2903
  }
2882
2904
  } else identifier = uriParsed.identifier;
@@ -2890,9 +2912,10 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
2890
2912
  status: 410,
2891
2913
  headers: { "Access-Control-Allow-Origin": "*" }
2892
2914
  });
2915
+ const actorUri = context.getActorUri(identifier);
2893
2916
  const links = [{
2894
2917
  rel: "self",
2895
- href: context.getActorUri(identifier).href,
2918
+ href: actorUri.href,
2896
2919
  type: "application/activity+json"
2897
2920
  }];
2898
2921
  for (const url of actor.urls) if (url instanceof _fedify_vocab.Link && url.href != null) links.push({
@@ -2916,23 +2939,19 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
2916
2939
  const customLinks = await webFingerLinksDispatcher(context, resourceUrl);
2917
2940
  if (customLinks != null) for (const link of customLinks) links.push(link);
2918
2941
  }
2919
- const aliases = [];
2920
- const preferredUsername = actor.preferredUsername;
2921
- if (resourceUrl.protocol != "acct:" && preferredUsername != null) {
2922
- aliases.push(`acct:${preferredUsername}@${host ?? context.url.host}`);
2923
- if (host != null && host !== context.url.host) aliases.push(`acct:${preferredUsername}@${context.url.host}`);
2924
- }
2925
- if (resourceUrl.href !== context.getActorUri(identifier).href) aliases.push(context.getActorUri(identifier).href);
2926
- if (resourceUrl.protocol === "acct:" && host != null && host !== context.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
2927
- const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
2928
- aliases.push(`acct:${username}@${host}`);
2929
- }
2930
- const jrd = {
2931
- subject: resourceUrl.href,
2942
+ const { subject, aliases } = getWebFingerSubjectAndAliases({
2943
+ resourceUrl,
2944
+ actorUri,
2945
+ preferredUsername: actor.preferredUsername,
2946
+ acctUsername,
2947
+ host,
2948
+ contextHost: context.url.host
2949
+ });
2950
+ return new Response(JSON.stringify({
2951
+ subject,
2932
2952
  aliases,
2933
2953
  links
2934
- };
2935
- return new Response(JSON.stringify(jrd), { headers: {
2954
+ }), { headers: {
2936
2955
  "Content-Type": "application/jrd+json",
2937
2956
  "Access-Control-Allow-Origin": "*"
2938
2957
  } });
@@ -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-BUiHyCQ9.cjs");
3
+ const require_middleware = require("./middleware-Bj5UFOaT.cjs");
4
4
  exports.FederationImpl = require_middleware.FederationImpl;
@@ -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 { _ as version, a as verifyRequestDetailed, d as validateCryptoKey, f as formatAcceptSignature, g as name, i as verifyRequest, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, u as importJwk } from "./http-C-9duWvR.js";
6
- import { _ as hasSignatureLike, b as signJsonLd, c as getKeyOwner, f as compactJsonLd, g as hasSignature, h as getNormalizationContextLoader, i as verifyObject, l as InvalidContextReferenceError, m as detachSignature, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, r as signObject, s as doesActorOwnKey, u as assertSafeJsonLd, v as isClearlyMalformedContextReference, w as wrapContextLoaderForJsonLd, x as verifyCompactJsonLd, y as isInvalidUrlTypeError } from "./proof-IyDe0jjt.js";
7
- import { n as getNodeInfo, t as nodeInfoToJson } from "./types-CAY3OdLq.js";
8
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-8o7zAqEi.js";
5
+ import { _ as version, a as verifyRequestDetailed, d as validateCryptoKey, f as formatAcceptSignature, g as name, i as verifyRequest, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, u as importJwk } from "./http-C-FdpmAl.js";
6
+ import { _ as hasSignatureLike, b as signJsonLd, c as getKeyOwner, f as compactJsonLd, g as hasSignature, h as getNormalizationContextLoader, i as verifyObject, l as InvalidContextReferenceError, m as detachSignature, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, r as signObject, s as doesActorOwnKey, u as assertSafeJsonLd, v as isClearlyMalformedContextReference, w as wrapContextLoaderForJsonLd, x as verifyCompactJsonLd, y as isInvalidUrlTypeError } from "./proof-DA_wkPds.js";
7
+ import { n as getNodeInfo, t as nodeInfoToJson } from "./types-DTONwNqL.js";
8
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-BjlL4Zk0.js";
9
9
  import { getLogger, withContext } from "@logtape/logtape";
10
10
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
11
11
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
@@ -222,6 +222,8 @@ var FederationBuilderImpl = class {
222
222
  f.webFingerLinksDispatcher = this.webFingerLinksDispatcher;
223
223
  f.objectCallbacks = { ...this.objectCallbacks };
224
224
  f.objectTypeIds = { ...this.objectTypeIds };
225
+ f.collectionCallbacks = { ...this.collectionCallbacks };
226
+ f.collectionTypeIds = { ...this.collectionTypeIds };
225
227
  f.inboxPath = this.inboxPath;
226
228
  f.outboxPath = this.outboxPath;
227
229
  f.inboxCallbacks = this.inboxCallbacks == null ? void 0 : { ...this.inboxCallbacks };
@@ -2807,6 +2809,24 @@ const logger = getLogger([
2807
2809
  "webfinger",
2808
2810
  "server"
2809
2811
  ]);
2812
+ function getWebFingerSubjectAndAliases({ resourceUrl, actorUri, preferredUsername, acctUsername, host, contextHost }) {
2813
+ const aliases = [];
2814
+ let subject = resourceUrl.href;
2815
+ if (resourceUrl.protocol != "acct:" && preferredUsername != null) {
2816
+ aliases.push(`acct:${preferredUsername}@${host ?? contextHost}`);
2817
+ if (host != null && host !== contextHost) aliases.push(`acct:${preferredUsername}@${contextHost}`);
2818
+ }
2819
+ if (resourceUrl.href !== actorUri.href) aliases.push(actorUri.href);
2820
+ if (resourceUrl.protocol === "acct:" && host != null && host !== contextHost && !resourceUrl.href.endsWith(`@${host}`)) {
2821
+ subject = `acct:${preferredUsername ?? acctUsername}@${host}`;
2822
+ aliases.push(resourceUrl.href);
2823
+ if (preferredUsername != null && preferredUsername !== "" && preferredUsername !== acctUsername) aliases.push(`acct:${preferredUsername}@${contextHost}`);
2824
+ }
2825
+ return {
2826
+ subject,
2827
+ aliases
2828
+ };
2829
+ }
2810
2830
  /**
2811
2831
  * Handles a WebFinger request. You would not typically call this function
2812
2832
  * directly, but instead use {@link Federation.fetch} method.
@@ -2861,6 +2881,7 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
2861
2881
  return identifier;
2862
2882
  }
2863
2883
  let identifier = null;
2884
+ let acctUsername = null;
2864
2885
  const uriParsed = context.parseUri(resourceUrl);
2865
2886
  if (uriParsed?.type != "actor") {
2866
2887
  const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
@@ -2874,8 +2895,9 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
2874
2895
  const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
2875
2896
  if (normalizedHost != context.url.host && normalizedHost != host) return await onNotFound(request);
2876
2897
  else {
2877
- identifier = await mapUsernameToIdentifier(match[1]);
2878
- resourceUrl = new URL(`acct:${match[1]}@${normalizedHost}`);
2898
+ acctUsername = match[1];
2899
+ identifier = await mapUsernameToIdentifier(acctUsername);
2900
+ resourceUrl = new URL(`acct:${acctUsername}@${normalizedHost}`);
2879
2901
  }
2880
2902
  }
2881
2903
  } else identifier = uriParsed.identifier;
@@ -2889,9 +2911,10 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
2889
2911
  status: 410,
2890
2912
  headers: { "Access-Control-Allow-Origin": "*" }
2891
2913
  });
2914
+ const actorUri = context.getActorUri(identifier);
2892
2915
  const links = [{
2893
2916
  rel: "self",
2894
- href: context.getActorUri(identifier).href,
2917
+ href: actorUri.href,
2895
2918
  type: "application/activity+json"
2896
2919
  }];
2897
2920
  for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
@@ -2915,23 +2938,19 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
2915
2938
  const customLinks = await webFingerLinksDispatcher(context, resourceUrl);
2916
2939
  if (customLinks != null) for (const link of customLinks) links.push(link);
2917
2940
  }
2918
- const aliases = [];
2919
- const preferredUsername = actor.preferredUsername;
2920
- if (resourceUrl.protocol != "acct:" && preferredUsername != null) {
2921
- aliases.push(`acct:${preferredUsername}@${host ?? context.url.host}`);
2922
- if (host != null && host !== context.url.host) aliases.push(`acct:${preferredUsername}@${context.url.host}`);
2923
- }
2924
- if (resourceUrl.href !== context.getActorUri(identifier).href) aliases.push(context.getActorUri(identifier).href);
2925
- if (resourceUrl.protocol === "acct:" && host != null && host !== context.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
2926
- const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
2927
- aliases.push(`acct:${username}@${host}`);
2928
- }
2929
- const jrd = {
2930
- subject: resourceUrl.href,
2941
+ const { subject, aliases } = getWebFingerSubjectAndAliases({
2942
+ resourceUrl,
2943
+ actorUri,
2944
+ preferredUsername: actor.preferredUsername,
2945
+ acctUsername,
2946
+ host,
2947
+ contextHost: context.url.host
2948
+ });
2949
+ return new Response(JSON.stringify({
2950
+ subject,
2931
2951
  aliases,
2932
2952
  links
2933
- };
2934
- return new Response(JSON.stringify(jrd), { headers: {
2953
+ }), { headers: {
2935
2954
  "Content-Type": "application/jrd+json",
2936
2955
  "Access-Control-Allow-Origin": "*"
2937
2956
  } });
@@ -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-C3JAusAj.mjs";
4
+ import { n as FederationImpl } from "./middleware-BJM6vrlT.mjs";
5
5
  export { FederationImpl };
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-NEN2KDMb.cjs");
8
- const require_middleware = require("./middleware-BUiHyCQ9.cjs");
9
- const require_proof = require("./proof-C2en2Cmb.cjs");
10
- const require_types = require("./types-KC4QAoxe.cjs");
11
- const require_kv_cache = require("./kv-cache-9K6uVGgd.cjs");
7
+ const require_http = require("./http-DLRpF855.cjs");
8
+ const require_middleware = require("./middleware-Bj5UFOaT.cjs");
9
+ const require_proof = require("./proof-BNGY2IU6.cjs");
10
+ const require_types = require("./types-m8u9L86X.cjs");
11
+ const require_kv_cache = require("./kv-cache-DKprbYof.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.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 verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "./http-C-9duWvR.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-Bk-ge16h.js";
8
- import { C as verifySignature, S as verifyJsonLd, _ as hasSignatureLike, a as verifyProof, b as signJsonLd, c as getKeyOwner, d as attachSignature, i as verifyObject, m as detachSignature, n as hasProofLike, p as createSignature, r as signObject, s as doesActorOwnKey, t as createProof } from "./proof-IyDe0jjt.js";
9
- import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "./types-CAY3OdLq.js";
10
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-8o7zAqEi.js";
6
+ import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "./http-C-FdpmAl.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-DOkcTiZ-.js";
8
+ import { C as verifySignature, S as verifyJsonLd, _ as hasSignatureLike, a as verifyProof, b as signJsonLd, c as getKeyOwner, d as attachSignature, i as verifyObject, m as detachSignature, n as hasProofLike, p as createSignature, r as signObject, s as doesActorOwnKey, t as createProof } from "./proof-DA_wkPds.js";
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-BjlL4Zk0.js";
11
11
  import { InProcessMessageQueue, MemoryKvStore, ParallelMessageQueue } from "./federation/mod.js";
12
12
  import "./nodeinfo/mod.js";
13
13
  import "./runtime/mod.js";
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as esm_default } from "../esm-DVILvP5e.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
6
  import "../std__assert-CRDpx_HF.mjs";
7
- import { a as parseProtocol, c as parseUsage, i as parseOutboundService, n as parseInboundService, o as parseServices, r as parseNodeInfo, s as parseSoftware, t as getNodeInfo } from "../client-D_1QpnWt.mjs";
7
+ import { a as parseProtocol, c as parseUsage, i as parseOutboundService, n as parseInboundService, o as parseServices, r as parseNodeInfo, s as parseSoftware, t as getNodeInfo } from "../client-dx126nMS.mjs";
8
8
  import { test } from "@fedify/fixture";
9
9
  //#region src/nodeinfo/client.test.ts
10
10
  test("getNodeInfo()", async (t) => {
@@ -62,6 +62,66 @@ test("getNodeInfo()", async (t) => {
62
62
  });
63
63
  esm_default.hardReset();
64
64
  });
65
+ test("getNodeInfo() blocks SSRF", async (t) => {
66
+ esm_default.spyGlobal();
67
+ await t.step("link href pointing to a loopback address", async () => {
68
+ esm_default.removeRoutes();
69
+ esm_default.get("https://example.com/.well-known/nodeinfo", { body: { links: [{
70
+ rel: "http://nodeinfo.diaspora.software/ns/schema/2.1",
71
+ href: "http://127.0.0.1:8080/internal"
72
+ }] } });
73
+ let internalFetched = false;
74
+ esm_default.get("http://127.0.0.1:8080/internal", () => {
75
+ internalFetched = true;
76
+ return { body: { secret: "INTERNAL_DATA_LEAKED" } };
77
+ });
78
+ assertEquals(await getNodeInfo("https://example.com/", { parse: "none" }), void 0);
79
+ assertEquals(internalFetched, false);
80
+ });
81
+ await t.step("link href using a data: URL", async () => {
82
+ esm_default.removeRoutes();
83
+ esm_default.get("https://example.com/.well-known/nodeinfo", { body: { links: [{
84
+ rel: "http://nodeinfo.diaspora.software/ns/schema/2.0",
85
+ href: "data:application/json,{\"software\":{\"name\":\"x\"}}"
86
+ }] } });
87
+ assertEquals(await getNodeInfo("https://example.com/", { parse: "none" }), void 0);
88
+ });
89
+ await t.step("redirect to a private address", async () => {
90
+ esm_default.removeRoutes();
91
+ esm_default.get("https://example.com/.well-known/nodeinfo", { body: { links: [{
92
+ rel: "http://nodeinfo.diaspora.software/ns/schema/2.1",
93
+ href: "https://example.com/nodeinfo/2.1"
94
+ }] } });
95
+ esm_default.get("https://example.com/nodeinfo/2.1", {
96
+ status: 302,
97
+ headers: { Location: "https://127.0.0.1:8080/internal" }
98
+ });
99
+ let internalFetched = false;
100
+ esm_default.get("https://127.0.0.1:8080/internal", () => {
101
+ internalFetched = true;
102
+ return { body: { secret: "INTERNAL_DATA_LEAKED" } };
103
+ });
104
+ assertEquals(await getNodeInfo("https://example.com/", { parse: "none" }), void 0);
105
+ assertEquals(internalFetched, false);
106
+ });
107
+ await t.step("direct fetch of a private address", async () => {
108
+ esm_default.removeRoutes();
109
+ let internalFetched = false;
110
+ esm_default.get("http://127.0.0.1:8080/nodeinfo", () => {
111
+ internalFetched = true;
112
+ return { body: { software: {
113
+ name: "x",
114
+ version: "1.0.0"
115
+ } } };
116
+ });
117
+ assertEquals(await getNodeInfo("http://127.0.0.1:8080/nodeinfo", {
118
+ direct: true,
119
+ parse: "none"
120
+ }), void 0);
121
+ assertEquals(internalFetched, false);
122
+ });
123
+ esm_default.hardReset();
124
+ });
65
125
  test("parseNodeInfo()", () => {
66
126
  const input = {
67
127
  software: {
@@ -5,7 +5,7 @@ import { r as createRequestContext } from "../context-Dk_tacqz.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
6
  import "../std__assert-CRDpx_HF.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
8
- import { _ as handleNodeInfoJrd, g as handleNodeInfo, o as createFederation } from "../middleware-C3JAusAj.mjs";
8
+ import { _ as handleNodeInfoJrd, g as handleNodeInfo, o as createFederation } from "../middleware-BJM6vrlT.mjs";
9
9
  import { test } from "@fedify/fixture";
10
10
  //#region src/nodeinfo/handler.test.ts
11
11
  test("handleNodeInfo()", async () => {
@@ -1,7 +1,7 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const require_types = require("../types-KC4QAoxe.cjs");
4
+ const require_types = require("../types-m8u9L86X.cjs");
5
5
  exports.getNodeInfo = require_types.getNodeInfo;
6
6
  exports.nodeInfoToJson = require_types.nodeInfoToJson;
7
7
  exports.parseNodeInfo = require_types.parseNodeInfo;
@@ -1,4 +1,4 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "../types-CAY3OdLq.js";
3
+ import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "../types-DTONwNqL.js";
4
4
  export { getNodeInfo, nodeInfoToJson, parseNodeInfo };
@@ -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-B0LcALOm.mjs";
5
- import "./key-BcpJR7wT.mjs";
4
+ import { n as version, t as name } from "./deno-B_vGx2Ji.mjs";
5
+ import "./key-6U1u5H_H.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-B0LcALOm.mjs";
5
- import { n as fetchKey, o as validateCryptoKey } from "./key-BcpJR7wT.mjs";
4
+ import { n as version, t as name } from "./deno-B_vGx2Ji.mjs";
5
+ import { n as fetchKey, o as validateCryptoKey } from "./key-6U1u5H_H.mjs";
6
6
  import { n as preloadedOnlyDocumentLoader } from "./public-audience-DYFHzm_c.mjs";
7
7
  import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-CNmZLixq.mjs";
8
8
  import { Activity, DataIntegrityProof, Multikey, getTypeId } from "@fedify/vocab";
@@ -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-NEN2KDMb.cjs");
4
+ const require_http = require("./http-DLRpF855.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,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { _ as version, d as validateCryptoKey, g as name, s as fetchKey } from "./http-C-9duWvR.js";
3
+ import { _ as version, d as validateCryptoKey, g as name, s as fetchKey } from "./http-C-FdpmAl.js";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, PUBLIC_COLLECTION, getTypeId, isActor } from "@fedify/vocab";
6
6
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
@@ -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-B0LcALOm.mjs";
5
- import { n as doubleKnock } from "./http-BkivuOe4.mjs";
4
+ import { n as version, t as name } from "./deno-B_vGx2Ji.mjs";
5
+ import { n as doubleKnock } from "./http-BlHW6_Oi.mjs";
6
6
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  //#region src/federation/send.ts
@@ -7,8 +7,8 @@ import { i as assertExists, t as assertStringIncludes } from "../std__assert-CRD
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-DikXweDx.mjs";
10
- import { t as exportJwk } from "../key-BcpJR7wT.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, u as verifyRequestDetailed } from "../http-BkivuOe4.mjs";
10
+ import { t as exportJwk } from "../key-6U1u5H_H.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, u as verifyRequestDetailed } from "../http-BlHW6_Oi.mjs";
12
12
  import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-DGu1NFwu.mjs";
13
13
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
14
14
  import { FetchError, exportSpki } from "@fedify/vocab-runtime";
@@ -5,7 +5,7 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import "../std__assert-CRDpx_HF.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
8
- import { a as importJwk, i as generateCryptoKeyPair, n as fetchKey, o as validateCryptoKey, r as fetchKeyDetailed, t as exportJwk } from "../key-BcpJR7wT.mjs";
8
+ import { a as importJwk, i as generateCryptoKeyPair, n as fetchKey, o as validateCryptoKey, r as fetchKeyDetailed, t as exportJwk } from "../key-6U1u5H_H.mjs";
9
9
  import { c as rsaPublicKey3, i as rsaPrivateKey2, o as rsaPublicKey1, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
10
10
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { CryptographicKey, Multikey } from "@fedify/vocab";
@@ -5,9 +5,9 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
6
6
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
7
7
  import { t as assert } from "../assert-DikXweDx.mjs";
8
- import { i as generateCryptoKeyPair } from "../key-BcpJR7wT.mjs";
8
+ import { i as generateCryptoKeyPair } from "../key-6U1u5H_H.mjs";
9
9
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
10
- import { a as compactJsonLd, f as isInvalidUrlTypeError, g as verifySignature, h as verifyJsonLd, i as attachSignature, n as UnsafeJsonLdError, o as createSignature, p as signJsonLd, s as detachSignature, u as hasSignatureLike } from "../ld-DAZQsoKN.mjs";
10
+ import { a as compactJsonLd, f as isInvalidUrlTypeError, g as verifySignature, h as verifyJsonLd, i as attachSignature, n as UnsafeJsonLdError, o as createSignature, p as signJsonLd, s as detachSignature, u as hasSignatureLike } from "../ld-DDBxn1rq.mjs";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  import { CryptographicKey } from "@fedify/vocab";
13
13
  import { encodeBase64 } from "byte-encodings/base64";
package/dist/sig/mod.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const require_http = require("../http-NEN2KDMb.cjs");
5
- const require_proof = require("../proof-C2en2Cmb.cjs");
4
+ const require_http = require("../http-DLRpF855.cjs");
5
+ const require_proof = require("../proof-BNGY2IU6.cjs");
6
6
  exports.attachSignature = require_proof.attachSignature;
7
7
  exports.createProof = require_proof.createProof;
8
8
  exports.createSignature = require_proof.createSignature;
package/dist/sig/mod.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-C-9duWvR.js";
4
- import { C as verifySignature, S as verifyJsonLd, _ as hasSignatureLike, a as verifyProof, b as signJsonLd, c as getKeyOwner, d as attachSignature, i as verifyObject, m as detachSignature, n as hasProofLike, p as createSignature, r as signObject, s as doesActorOwnKey, t as createProof } from "../proof-IyDe0jjt.js";
3
+ import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-C-FdpmAl.js";
4
+ import { C as verifySignature, S as verifyJsonLd, _ as hasSignatureLike, a as verifyProof, b as signJsonLd, c as getKeyOwner, d as attachSignature, i as verifyObject, m as detachSignature, n as hasProofLike, p as createSignature, r as signObject, s as doesActorOwnKey, t as createProof } from "../proof-DA_wkPds.js";
5
5
  export { attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
@@ -6,7 +6,7 @@ import "../std__assert-CRDpx_HF.mjs";
6
6
  import { n as assertFalse } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assert } from "../assert-DikXweDx.mjs";
8
8
  import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-DGu1NFwu.mjs";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-CwVIBwY0.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-vuyMTd_f.mjs";
10
10
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { Create, CryptographicKey, lookupObject } from "@fedify/vocab";
12
12
  //#region src/sig/owner.test.ts
@@ -8,7 +8,7 @@ import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
8
8
  import { t as assert } from "../assert-DikXweDx.mjs";
9
9
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
10
10
  import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-CNmZLixq.mjs";
11
- import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-wrxzZi_u.mjs";
11
+ import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-BGrdGhcb.mjs";
12
12
  import { mockDocumentLoader, test } from "@fedify/fixture";
13
13
  import { Create, DataIntegrityProof, Document, Multikey, Note, PUBLIC_COLLECTION, Place } from "@fedify/vocab";
14
14
  import { decodeMultibase, importMultibaseKey } from "@fedify/vocab-runtime";
@@ -1,7 +1,7 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { c as getNormalizationContextLoader } from "./ld-DAZQsoKN.mjs";
4
+ import { c as getNormalizationContextLoader } from "./ld-DDBxn1rq.mjs";
5
5
  import jsonld from "@fedify/vocab-runtime/jsonld";
6
6
  //#region src/federation/temporal.ts
7
7
  function isPlainObject(value) {