@fedify/fedify 2.4.0-dev.2164 → 2.4.0-dev.2190
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.
- package/dist/{builder-BqRmnx7p.mjs → builder-CFF0YNTp.mjs} +3 -3
- package/dist/{circuit-breaker-C5NqoLBJ.mjs → circuit-breaker-XJ53md4S.mjs} +16 -11
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{compound-proof-CxDBdtNz.mjs → compound-proof-F2jjkrt0.mjs} +3 -3
- package/dist/{context-BykNUf04.d.ts → context-9T--NSo4.d.ts} +55 -1
- package/dist/{context-L0Fnib9j.d.cts → context-CDcAgm4l.d.cts} +55 -1
- package/dist/{deno-CizGaYeG.mjs → deno-EopndaNb.mjs} +1 -1
- package/dist/{docloader-BBFAItNB.mjs → docloader-u6zzOExF.mjs} +25 -17
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/circuit-breaker.test.mjs +50 -1
- package/dist/federation/compound-fanout.test.mjs +3 -3
- package/dist/federation/handler-compound-proof.test.mjs +3 -3
- package/dist/federation/handler.test.mjs +5 -5
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/keycache.test.mjs +1 -1
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +137 -13
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +5 -5
- package/dist/federation/portable-actor.test.mjs +3 -3
- package/dist/federation/portable-chain.test.mjs +3 -3
- package/dist/federation/portable-collection.test.mjs +4 -4
- package/dist/federation/portable-gateway-keys.test.mjs +6 -6
- package/dist/federation/portable-inbox.test.mjs +35 -5
- package/dist/federation/portable-parse-uri.test.mjs +1 -1
- package/dist/federation/portable-route-activity.test.d.mts +2 -0
- package/dist/federation/portable-route-activity.test.mjs +259 -0
- package/dist/federation/portable.test.mjs +3 -3
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/tasks/enqueue.test.mjs +1 -1
- package/dist/federation/tasks/tasks.test.mjs +2 -2
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +1 -1
- package/dist/{federation-DFCnp94y.cjs → federation-BSS2dUO7.cjs} +38 -21
- package/dist/{http-Baovr6xq.js → http-BqN5kyUf.js} +426 -141
- package/dist/{http-DC1cqAQ2.d.cts → http-BrwKINQn.d.cts} +28 -0
- package/dist/{http-R4g1McwE.cjs → http-CCr2_ipG.cjs} +443 -140
- package/dist/{http-Cok5-vIC.d.ts → http-DGx0KOws.d.ts} +28 -0
- package/dist/{http-DRH0n8TD.mjs → http-Y1ObT1A8.mjs} +180 -92
- package/dist/{key-D5awqp7u.mjs → key-DyXf88bq.mjs} +4 -4
- package/dist/{key-owner-evidence-Bo3yaeL5.mjs → key-owner-evidence-APB6NpSk.mjs} +1 -1
- package/dist/{keycache-PiOM9pM0.mjs → keycache-Da8A8mZa.mjs} +1 -1
- package/dist/{kv-cache-CZiBDLPi.js → kv-cache-C02XitwK.js} +24 -16
- package/dist/{kv-cache-C7RWL7hz.mjs → kv-cache-C8YjNAi_.mjs} +1 -1
- package/dist/{kv-cache-Ct-KWRta.cjs → kv-cache-DUXluAc0.cjs} +23 -15
- package/dist/{ld-CyliEU48.mjs → ld-oQj6j_hP.mjs} +3 -3
- package/dist/{metrics-CFBEehTc.mjs → metrics-zMe834ID.mjs} +1 -1
- package/dist/{middleware-B99JjvFn.mjs → middleware-Bdu2-OPD.mjs} +37 -25
- package/dist/{middleware-CdpTFsa2.js → middleware-CaR2MRWY.js} +39 -22
- package/dist/{middleware-BmqEWsWP.mjs → middleware-Ck9yghxs.mjs} +1 -1
- package/dist/{mod-DK0y9fd-.d.ts → mod-B3OBLj5g.d.ts} +1 -1
- package/dist/{mod-B5z_q9TH.d.ts → mod-C5Mwx5ty.d.ts} +5 -1
- package/dist/{mod--jv6vyrP.d.ts → mod-Ck9_lSJB.d.ts} +1 -1
- package/dist/{mod-BLOXGs6m.d.cts → mod-D58KCqUg.d.cts} +1 -1
- package/dist/{mod-CPPqkyV_.d.cts → mod-DHTuu3l8.d.cts} +1 -1
- package/dist/{mod-BA_F2x53.d.cts → mod-Dp3Ij7sw.d.cts} +5 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +5 -5
- package/dist/mod.d.ts +5 -5
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-DKdtsrEq.mjs → owner-Dem4fbwc.mjs} +5 -5
- package/dist/{portable-collection-uv4CuQXm.js → portable-collection-BEqLrMW3.js} +1 -1
- package/dist/{portable-collection-Cb5cdPIU.mjs → portable-collection-BL6aZlQ0.mjs} +2 -2
- package/dist/{portable-collection-UajqDrSL.cjs → portable-collection-DJe_bk50.cjs} +1 -1
- package/dist/{portable-key-Bv1RdQ0n.mjs → portable-key-Duue9Y2Y.mjs} +209 -56
- package/dist/{portable-key-id-Bg259c4Z.mjs → portable-key-id-Ca30-hOa.mjs} +45 -1
- package/dist/{proof-CRTPWbVh.mjs → proof-C9115DX_.mjs} +5 -5
- package/dist/{send-2dULlZc8.mjs → send-D0hxFFRB.mjs} +3 -3
- package/dist/sig/compound-proof-discovery.test.mjs +1 -1
- package/dist/sig/compound-proof-producer.test.mjs +1 -1
- package/dist/sig/compound-proof-verification.test.mjs +2 -2
- package/dist/sig/compound-proof.test.mjs +2 -2
- package/dist/sig/http.test.mjs +495 -23
- package/dist/sig/key-owner-evidence.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.d.cts +2 -2
- package/dist/sig/mod.d.ts +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +1 -1
- package/dist/sig/portable-key-id.test.d.mts +2 -0
- package/dist/sig/portable-key-id.test.mjs +67 -0
- package/dist/sig/portable-key.test.mjs +253 -7
- package/dist/sig/proof.test.mjs +3 -3
- package/dist/{temporal-Dhsk6aUT.mjs → temporal-DKchpKyp.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +52 -0
- package/dist/utils/docloader.test.mjs +93 -2
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.d.cts +1 -1
- package/dist/utils/mod.d.ts +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +6 -6
|
@@ -601,6 +601,30 @@ interface VerifyRequestOptions {
|
|
|
601
601
|
*/
|
|
602
602
|
spec?: HttpMessageSignaturesSpec;
|
|
603
603
|
/**
|
|
604
|
+
* The maximum number of [RFC 9421] signatures of a request to verify.
|
|
605
|
+
* A request can carry several signatures, each of which may make Fedify
|
|
606
|
+
* fetch the key that it names, so only the first ones in the order of
|
|
607
|
+
* the `Signature-Input` header are verified, and the rest are ignored as
|
|
608
|
+
* if they were absent. Every signature among the first ones counts, even
|
|
609
|
+
* if it fails before its key is fetched, e.g., because it is too old, or
|
|
610
|
+
* names the same key as another one. The key of a key ID is looked up
|
|
611
|
+
* only once for all the signatures that name it.
|
|
612
|
+
*
|
|
613
|
+
* It has to be a positive integer, or `Infinity` to verify every
|
|
614
|
+
* signature, which lets a single request make Fedify fetch any number of
|
|
615
|
+
* keys. Draft-cavage HTTP Signatures carry a single signature, so this
|
|
616
|
+
* option does not affect them.
|
|
617
|
+
*
|
|
618
|
+
* Three by default.
|
|
619
|
+
*
|
|
620
|
+
* [RFC 9421]: https://www.rfc-editor.org/rfc/rfc9421
|
|
621
|
+
* @throws {RangeError} Thrown by {@link verifyRequest} and
|
|
622
|
+
* {@link verifyRequestDetailed} if the value is not a positive
|
|
623
|
+
* integer or `Infinity`.
|
|
624
|
+
* @since 2.4.0
|
|
625
|
+
*/
|
|
626
|
+
maxSignatures?: number;
|
|
627
|
+
/**
|
|
604
628
|
* The OpenTelemetry tracer provider. If omitted, the global tracer provider
|
|
605
629
|
* is used.
|
|
606
630
|
* @since 1.3.0
|
|
@@ -651,6 +675,8 @@ type VerifyRequestDetailedResult = {
|
|
|
651
675
|
* @param options Options for verifying the request.
|
|
652
676
|
* @returns The public key of the verified signature, or `null` if the signature
|
|
653
677
|
* could not be verified.
|
|
678
|
+
* @throws {RangeError} Thrown if {@link VerifyRequestOptions.maxSignatures}
|
|
679
|
+
* is not a positive integer or `Infinity`.
|
|
654
680
|
*/
|
|
655
681
|
declare function verifyRequest(request: Request, options?: VerifyRequestOptions): Promise<CryptographicKey | null>;
|
|
656
682
|
/**
|
|
@@ -660,6 +686,8 @@ declare function verifyRequest(request: Request, options?: VerifyRequestOptions)
|
|
|
660
686
|
* @param request The request to verify.
|
|
661
687
|
* @param options Options for verifying the request.
|
|
662
688
|
* @returns The verified public key, or a structured verification failure.
|
|
689
|
+
* @throws {RangeError} Thrown if {@link VerifyRequestOptions.maxSignatures}
|
|
690
|
+
* is not a positive integer or `Infinity`.
|
|
663
691
|
* @since 2.1.0
|
|
664
692
|
*/
|
|
665
693
|
declare function verifyRequestDetailed(request: Request, options?: VerifyRequestOptions): Promise<VerifyRequestDetailedResult>;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-
|
|
4
|
+
import { n as version, t as name } from "./deno-EopndaNb.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-zMe834ID.mjs";
|
|
6
6
|
import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CPVqki78.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import { a as promoteKeyOwnerEvidence } from "./key-owner-evidence-
|
|
9
|
-
import { a as fetchKeyDetailed, c as validateCryptoKey, t as bypassKeyCacheReads } from "./key-
|
|
10
|
-
import { n as resolvePortableActorKey, r as verifyPortableGatewayKeyDocument } from "./portable-key-
|
|
7
|
+
import { m as parseKeyIdString } from "./portable-key-id-Ca30-hOa.mjs";
|
|
8
|
+
import { a as promoteKeyOwnerEvidence } from "./key-owner-evidence-APB6NpSk.mjs";
|
|
9
|
+
import { a as fetchKeyDetailed, c as validateCryptoKey, t as bypassKeyCacheReads } from "./key-DyXf88bq.mjs";
|
|
10
|
+
import { n as resolvePortableActorKey, r as verifyPortableGatewayKeyDocument } from "./portable-key-Duue9Y2Y.mjs";
|
|
11
11
|
import { getLogger } from "@logtape/logtape";
|
|
12
12
|
import { CryptographicKey } from "@fedify/vocab";
|
|
13
13
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -215,16 +215,19 @@ function parseDraftSignature(signature) {
|
|
|
215
215
|
* Lists the HTTP Signatures that a request claims to carry, without verifying
|
|
216
216
|
* any of them. Signatures whose key IDs are not URLs are left out.
|
|
217
217
|
* @param request The request.
|
|
218
|
+
* @param maxSignatures The maximum number of RFC 9421 signatures to consider,
|
|
219
|
+
* counted the same way as by {@link verifyRequest}, so
|
|
220
|
+
* that the signatures it ignores are not listed either.
|
|
218
221
|
* @returns The signatures; RFC 9421 ones if the request has
|
|
219
222
|
* a `Signature-Input` header, or a draft-cavage one otherwise.
|
|
220
223
|
* @internal
|
|
221
224
|
*/
|
|
222
|
-
function listRequestSignatures(request) {
|
|
225
|
+
function listRequestSignatures(request, maxSignatures = 3) {
|
|
223
226
|
const signatureInput = request.headers.get("Signature-Input");
|
|
224
227
|
if (signatureInput != null) {
|
|
225
228
|
const signatures = [];
|
|
226
|
-
const inputs = parseRfc9421SignatureInput(signatureInput);
|
|
227
|
-
for (const [label, input] of
|
|
229
|
+
const inputs = Object.entries(parseRfc9421SignatureInput(signatureInput));
|
|
230
|
+
for (const [label, input] of inputs.slice(0, maxSignatures)) {
|
|
228
231
|
const keyId = parseKeyId(input.keyId);
|
|
229
232
|
if (keyId == null) continue;
|
|
230
233
|
signatures.push({
|
|
@@ -352,6 +355,18 @@ async function signRequestRfc9421(request, privateKey, keyId, span, currentTime,
|
|
|
352
355
|
body
|
|
353
356
|
});
|
|
354
357
|
}
|
|
358
|
+
/**
|
|
359
|
+
* Checks that a maximum number of signatures to verify is a positive safe
|
|
360
|
+
* integer or `Infinity`.
|
|
361
|
+
* @param value The value to check.
|
|
362
|
+
* @param name The name of the option, used in the error message.
|
|
363
|
+
* @throws {RangeError} Thrown if the value is not valid.
|
|
364
|
+
* @internal
|
|
365
|
+
*/
|
|
366
|
+
function validateMaxSignatures(value, name) {
|
|
367
|
+
if (value === Infinity || Number.isSafeInteger(value) && value >= 1) return;
|
|
368
|
+
throw new RangeError(`${name} must be a positive integer or Infinity.`);
|
|
369
|
+
}
|
|
355
370
|
const supportedHashAlgorithms = {
|
|
356
371
|
"sha": "SHA-1",
|
|
357
372
|
"sha-256": "SHA-256",
|
|
@@ -444,6 +459,8 @@ function recordVerificationResult(span, result) {
|
|
|
444
459
|
* @param options Options for verifying the request.
|
|
445
460
|
* @returns The public key of the verified signature, or `null` if the signature
|
|
446
461
|
* could not be verified.
|
|
462
|
+
* @throws {RangeError} Thrown if {@link VerifyRequestOptions.maxSignatures}
|
|
463
|
+
* is not a positive integer or `Infinity`.
|
|
447
464
|
*/
|
|
448
465
|
async function verifyRequest(request, options = {}) {
|
|
449
466
|
const result = await verifyRequestDetailed(request, options);
|
|
@@ -456,9 +473,12 @@ async function verifyRequest(request, options = {}) {
|
|
|
456
473
|
* @param request The request to verify.
|
|
457
474
|
* @param options Options for verifying the request.
|
|
458
475
|
* @returns The verified public key, or a structured verification failure.
|
|
476
|
+
* @throws {RangeError} Thrown if {@link VerifyRequestOptions.maxSignatures}
|
|
477
|
+
* is not a positive integer or `Infinity`.
|
|
459
478
|
* @since 2.1.0
|
|
460
479
|
*/
|
|
461
480
|
async function verifyRequestDetailed(request, options = {}) {
|
|
481
|
+
if (options.maxSignatures !== void 0) validateMaxSignatures(options.maxSignatures, "maxSignatures");
|
|
462
482
|
return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("http_signatures.verify", async (span) => {
|
|
463
483
|
if (span.isRecording()) {
|
|
464
484
|
span.setAttribute(ATTR_HTTP_REQUEST_METHOD, request.method);
|
|
@@ -767,7 +787,100 @@ async function verifyRfc9421ContentDigest(digestHeader, body) {
|
|
|
767
787
|
}
|
|
768
788
|
return false;
|
|
769
789
|
}
|
|
770
|
-
|
|
790
|
+
/**
|
|
791
|
+
* Verifies one RFC 9421 signature of a request with a key.
|
|
792
|
+
* @param request The request, whose body may be consumed already.
|
|
793
|
+
* @param sigInput The parsed `Signature-Input` member of the signature.
|
|
794
|
+
* @param sigBytes The bytes of the signature.
|
|
795
|
+
* @param key The public key named by the signature.
|
|
796
|
+
* @param span The span to record the algorithm and the signature on.
|
|
797
|
+
* @returns Whether the signature is verified, and the algorithm of the
|
|
798
|
+
* signature if it is supported.
|
|
799
|
+
*/
|
|
800
|
+
async function verifyRfc9421SignatureWithKey(request, sigInput, sigBytes, key, span) {
|
|
801
|
+
const logger = getLogger([
|
|
802
|
+
"fedify",
|
|
803
|
+
"sig",
|
|
804
|
+
"http"
|
|
805
|
+
]);
|
|
806
|
+
let alg = sigInput.alg?.toLowerCase();
|
|
807
|
+
if (alg == null) {
|
|
808
|
+
if (key.publicKey.algorithm.name === "RSASSA-PKCS1-v1_5") alg = "hash" in key.publicKey.algorithm ? key.publicKey.algorithm.hash === "SHA-512" ? "rsa-v1_5-sha512" : "rsa-v1_5-sha256" : "rsa-v1_5-sha256";
|
|
809
|
+
else if (key.publicKey.algorithm.name === "RSA-PSS") alg = "rsa-pss-sha512";
|
|
810
|
+
else if (key.publicKey.algorithm.name === "ECDSA") alg = "namedCurve" in key.publicKey.algorithm && key.publicKey.algorithm.namedCurve === "P-256" ? "ecdsa-p256-sha256" : "ecdsa-p384-sha384";
|
|
811
|
+
else if (key.publicKey.algorithm.name === "Ed25519") alg = "ed25519";
|
|
812
|
+
}
|
|
813
|
+
if (alg) span?.setAttribute("http_signatures.algorithm", alg);
|
|
814
|
+
const algorithm = alg && rfc9421AlgorithmMap[alg];
|
|
815
|
+
if (!algorithm) {
|
|
816
|
+
logger.debug("Failed to verify; unsupported algorithm: {algorithm}", {
|
|
817
|
+
algorithm: sigInput.alg,
|
|
818
|
+
supported: Object.keys(rfc9421AlgorithmMap)
|
|
819
|
+
});
|
|
820
|
+
return {
|
|
821
|
+
verified: false,
|
|
822
|
+
mismatched: false
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
const metricAlgorithm = alg;
|
|
826
|
+
let signatureBase;
|
|
827
|
+
try {
|
|
828
|
+
signatureBase = createRfc9421SignatureBase(request, sigInput.components, sigInput.parameters);
|
|
829
|
+
} catch (error) {
|
|
830
|
+
logger.debug("Failed to create signature base for verification: {error}", {
|
|
831
|
+
error,
|
|
832
|
+
signatureInput: sigInput
|
|
833
|
+
});
|
|
834
|
+
return {
|
|
835
|
+
verified: false,
|
|
836
|
+
algorithm: metricAlgorithm,
|
|
837
|
+
mismatched: false
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
const signatureBaseBytes = new TextEncoder().encode(signatureBase);
|
|
841
|
+
span?.setAttribute("http_signatures.signature", encodeHex(sigBytes));
|
|
842
|
+
const algorithmName = typeof algorithm === "string" ? algorithm : algorithm.name;
|
|
843
|
+
if (key.publicKey.algorithm.name !== algorithmName) {
|
|
844
|
+
logger.debug("Failed to verify; key {keyId} is not a key for algorithm {algorithm}.", {
|
|
845
|
+
keyId: sigInput.keyId,
|
|
846
|
+
algorithm: alg
|
|
847
|
+
});
|
|
848
|
+
return {
|
|
849
|
+
verified: false,
|
|
850
|
+
algorithm: metricAlgorithm,
|
|
851
|
+
mismatched: true
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
let verified;
|
|
855
|
+
try {
|
|
856
|
+
verified = await crypto.subtle.verify(algorithm, key.publicKey, sigBytes.slice(), signatureBaseBytes);
|
|
857
|
+
} catch (error) {
|
|
858
|
+
logger.debug("Error during signature verification: {error}", {
|
|
859
|
+
error,
|
|
860
|
+
keyId: sigInput.keyId,
|
|
861
|
+
algorithm: sigInput.alg
|
|
862
|
+
});
|
|
863
|
+
return {
|
|
864
|
+
verified: false,
|
|
865
|
+
algorithm: metricAlgorithm,
|
|
866
|
+
mismatched: false
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
if (verified) return {
|
|
870
|
+
verified: true,
|
|
871
|
+
algorithm: metricAlgorithm
|
|
872
|
+
};
|
|
873
|
+
logger.debug("Failed to verify signature with key {keyId}; signature invalid.", {
|
|
874
|
+
keyId: sigInput.keyId,
|
|
875
|
+
signatureBase
|
|
876
|
+
});
|
|
877
|
+
return {
|
|
878
|
+
verified: false,
|
|
879
|
+
algorithm: metricAlgorithm,
|
|
880
|
+
mismatched: true
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
async function verifyRequestRfc9421(request, span, metricsContext, { documentLoader, contextLoader, timeWindow, currentTime, keyCache, maxSignatures = 3, meterProvider, tracerProvider } = {}) {
|
|
771
884
|
const logger = getLogger([
|
|
772
885
|
"fedify",
|
|
773
886
|
"sig",
|
|
@@ -780,7 +893,6 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
780
893
|
logger.error("Failed to verify; the request body is locked.", { url: request.url });
|
|
781
894
|
return noSignatureResult();
|
|
782
895
|
}
|
|
783
|
-
const originalRequest = request;
|
|
784
896
|
request = request.clone();
|
|
785
897
|
const signatureInputHeader = request.headers.get("Signature-Input");
|
|
786
898
|
if (!signatureInputHeader) {
|
|
@@ -800,6 +912,29 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
800
912
|
logger.debug("Failed to verify; no valid signatures found in Signature-Input header.", { header: signatureInputHeader });
|
|
801
913
|
return invalidSignatureResult(null);
|
|
802
914
|
}
|
|
915
|
+
if (signatureNames.length > maxSignatures) {
|
|
916
|
+
logger.debug("Verifying only the first {maxSignatures} of the {count} signatures in the Signature-Input header; the rest are ignored.", {
|
|
917
|
+
maxSignatures,
|
|
918
|
+
count: signatureNames.length
|
|
919
|
+
});
|
|
920
|
+
signatureNames.splice(maxSignatures);
|
|
921
|
+
}
|
|
922
|
+
const keyLookups = /* @__PURE__ */ new Map();
|
|
923
|
+
const refreshedKeyIds = /* @__PURE__ */ new Set();
|
|
924
|
+
const lookUpKey = (keyId, keyCache) => measureSignatureKeyFetch(meterProvider, "http", () => fetchKeyDetailed(keyId, CryptographicKey, {
|
|
925
|
+
documentLoader,
|
|
926
|
+
contextLoader,
|
|
927
|
+
keyCache,
|
|
928
|
+
tracerProvider,
|
|
929
|
+
meterProvider,
|
|
930
|
+
portableKeyResolvers: createPortableKeyResolvers({
|
|
931
|
+
documentLoader,
|
|
932
|
+
contextLoader,
|
|
933
|
+
keyCache,
|
|
934
|
+
tracerProvider,
|
|
935
|
+
meterProvider
|
|
936
|
+
})
|
|
937
|
+
}));
|
|
803
938
|
let failure = noSignatureResult();
|
|
804
939
|
let failureAlgorithm;
|
|
805
940
|
const setFailure = (result, algorithm) => {
|
|
@@ -873,94 +1008,40 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
873
1008
|
setFailure(invalidSignatureResult(null));
|
|
874
1009
|
continue;
|
|
875
1010
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
tracerProvider,
|
|
881
|
-
meterProvider,
|
|
882
|
-
portableKeyResolvers: createPortableKeyResolvers({
|
|
883
|
-
documentLoader,
|
|
884
|
-
contextLoader,
|
|
885
|
-
keyCache,
|
|
886
|
-
tracerProvider,
|
|
887
|
-
meterProvider
|
|
888
|
-
})
|
|
889
|
-
}));
|
|
890
|
-
if (fetchError != null) {
|
|
891
|
-
setFailure(keyFetchErrorResult(keyId, fetchError));
|
|
892
|
-
continue;
|
|
1011
|
+
let lookup = keyLookups.get(keyId.href);
|
|
1012
|
+
if (lookup == null) {
|
|
1013
|
+
lookup = await lookUpKey(keyId, keyCache);
|
|
1014
|
+
keyLookups.set(keyId.href, lookup);
|
|
893
1015
|
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
const candidateAlgorithm = algorithm ? alg : void 0;
|
|
909
|
-
if (!algorithm) {
|
|
910
|
-
logger.debug("Failed to verify; unsupported algorithm: {algorithm}", {
|
|
911
|
-
algorithm: sigInput.alg,
|
|
912
|
-
supported: Object.keys(rfc9421AlgorithmMap)
|
|
913
|
-
});
|
|
914
|
-
setFailure(invalidSignatureResult(keyId));
|
|
915
|
-
continue;
|
|
916
|
-
}
|
|
917
|
-
let signatureBase;
|
|
918
|
-
try {
|
|
919
|
-
signatureBase = createRfc9421SignatureBase(request, sigInput.components, sigInput.parameters);
|
|
920
|
-
} catch (error) {
|
|
921
|
-
logger.debug("Failed to create signature base for verification: {error}", {
|
|
922
|
-
error,
|
|
923
|
-
signatureInput: sigInput
|
|
924
|
-
});
|
|
925
|
-
setFailure(invalidSignatureResult(keyId), candidateAlgorithm);
|
|
926
|
-
continue;
|
|
927
|
-
}
|
|
928
|
-
const signatureBaseBytes = new TextEncoder().encode(signatureBase);
|
|
929
|
-
span?.setAttribute("http_signatures.signature", encodeHex(sigBytes));
|
|
930
|
-
try {
|
|
931
|
-
if (await crypto.subtle.verify(algorithm, key.publicKey, sigBytes.slice(), signatureBaseBytes)) {
|
|
932
|
-
metricsContext.algorithm = candidateAlgorithm;
|
|
1016
|
+
while (true) {
|
|
1017
|
+
const { key, cached, fetchError } = lookup;
|
|
1018
|
+
if (fetchError != null) {
|
|
1019
|
+
setFailure(keyFetchErrorResult(keyId, fetchError));
|
|
1020
|
+
break;
|
|
1021
|
+
}
|
|
1022
|
+
if (!key) {
|
|
1023
|
+
logger.debug("Failed to fetch key: {keyId}", { keyId: sigInput.keyId });
|
|
1024
|
+
setFailure(invalidSignatureResult(keyId));
|
|
1025
|
+
break;
|
|
1026
|
+
}
|
|
1027
|
+
const result = await verifyRfc9421SignatureWithKey(request, sigInput, sigBytes, key, span);
|
|
1028
|
+
if (result.verified) {
|
|
1029
|
+
metricsContext.algorithm = result.algorithm;
|
|
933
1030
|
return {
|
|
934
1031
|
verified: true,
|
|
935
1032
|
key,
|
|
936
1033
|
signatureLabel: sigName
|
|
937
1034
|
};
|
|
938
|
-
}
|
|
1035
|
+
}
|
|
1036
|
+
if (result.mismatched && cached && !refreshedKeyIds.has(keyId.href)) {
|
|
939
1037
|
logger.debug("Failed to verify with cached key {keyId}; retrying with fresh key...", { keyId: sigInput.keyId });
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
currentTime,
|
|
945
|
-
keyCache: bypassKeyCacheReads(keyCache),
|
|
946
|
-
spec: "rfc9421",
|
|
947
|
-
meterProvider,
|
|
948
|
-
tracerProvider
|
|
949
|
-
});
|
|
950
|
-
} else {
|
|
951
|
-
logger.debug("Failed to verify signature with fetched key {keyId}; signature invalid.", {
|
|
952
|
-
keyId: sigInput.keyId,
|
|
953
|
-
signatureBase
|
|
954
|
-
});
|
|
955
|
-
setFailure(invalidSignatureResult(keyId), candidateAlgorithm);
|
|
1038
|
+
refreshedKeyIds.add(keyId.href);
|
|
1039
|
+
lookup = await lookUpKey(keyId, bypassKeyCacheReads(keyCache));
|
|
1040
|
+
keyLookups.set(keyId.href, lookup);
|
|
1041
|
+
continue;
|
|
956
1042
|
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
error,
|
|
960
|
-
keyId: sigInput.keyId,
|
|
961
|
-
algorithm: sigInput.alg
|
|
962
|
-
});
|
|
963
|
-
setFailure(invalidSignatureResult(keyId), candidateAlgorithm);
|
|
1043
|
+
setFailure(invalidSignatureResult(keyId), result.algorithm);
|
|
1044
|
+
break;
|
|
964
1045
|
}
|
|
965
1046
|
}
|
|
966
1047
|
metricsContext.algorithm = failureAlgorithm;
|
|
@@ -1060,16 +1141,19 @@ async function doubleKnock(request, identity, options = {}) {
|
|
|
1060
1141
|
}
|
|
1061
1142
|
async function doubleKnockInternal(request, identity, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
1062
1143
|
const { specDeterminer, log, tracerProvider, signal } = options;
|
|
1144
|
+
signal?.throwIfAborted();
|
|
1063
1145
|
const maximumRedirection = options.maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
1064
1146
|
visited.add(request.url);
|
|
1065
1147
|
const origin = new URL(request.url).origin;
|
|
1066
1148
|
const firstTrySpec = specDeterminer == null ? "rfc9421" : await specDeterminer.determineSpec(origin);
|
|
1149
|
+
signal?.throwIfAborted();
|
|
1067
1150
|
const body = options.body !== void 0 ? options.body : request.method !== "GET" && request.method !== "HEAD" ? await request.clone().arrayBuffer() : null;
|
|
1068
1151
|
let signedRequest = await signRequest(request, identity.privateKey, identity.keyId, {
|
|
1069
1152
|
spec: firstTrySpec,
|
|
1070
1153
|
tracerProvider,
|
|
1071
1154
|
body
|
|
1072
1155
|
});
|
|
1156
|
+
signal?.throwIfAborted();
|
|
1073
1157
|
log?.(signedRequest);
|
|
1074
1158
|
let response = await fetchDoubleKnockRequest(request, signedRequest, signal);
|
|
1075
1159
|
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
@@ -1094,6 +1178,7 @@ async function doubleKnockInternal(request, identity, options, redirected = 0, v
|
|
|
1094
1178
|
let fulfilled = false;
|
|
1095
1179
|
let challengeRequest;
|
|
1096
1180
|
for (const entry of entries) {
|
|
1181
|
+
signal?.throwIfAborted();
|
|
1097
1182
|
const rfc9421 = fulfillAcceptSignature(entry, localKeyId, localAlg);
|
|
1098
1183
|
if (rfc9421 == null) continue;
|
|
1099
1184
|
logger.debug("Received Accept-Signature challenge; accumulating label {label} and components {components}.", {
|
|
@@ -1116,6 +1201,7 @@ async function doubleKnockInternal(request, identity, options, redirected = 0, v
|
|
|
1116
1201
|
}
|
|
1117
1202
|
}
|
|
1118
1203
|
if (fulfilled && challengeRequest != null) {
|
|
1204
|
+
signal?.throwIfAborted();
|
|
1119
1205
|
signedRequest = challengeRequest;
|
|
1120
1206
|
log?.(signedRequest);
|
|
1121
1207
|
response = await fetch(signedRequest, {
|
|
@@ -1140,11 +1226,13 @@ async function doubleKnockInternal(request, identity, options, redirected = 0, v
|
|
|
1140
1226
|
status: response.status,
|
|
1141
1227
|
statusText: response.statusText
|
|
1142
1228
|
});
|
|
1229
|
+
signal?.throwIfAborted();
|
|
1143
1230
|
signedRequest = await signRequest(request, identity.privateKey, identity.keyId, {
|
|
1144
1231
|
spec,
|
|
1145
1232
|
tracerProvider,
|
|
1146
1233
|
body
|
|
1147
1234
|
});
|
|
1235
|
+
signal?.throwIfAborted();
|
|
1148
1236
|
log?.(signedRequest);
|
|
1149
1237
|
response = await fetchDoubleKnockRequest(request, signedRequest, signal);
|
|
1150
1238
|
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
@@ -1187,4 +1275,4 @@ function timingSafeEqual(a, b) {
|
|
|
1187
1275
|
return result === 0;
|
|
1188
1276
|
}
|
|
1189
1277
|
//#endregion
|
|
1190
|
-
export { listRequestSignatures as a, selectRequestSignature as c,
|
|
1278
|
+
export { listRequestSignatures as a, selectRequestSignature as c, validateMaxSignatures as d, verifyRequest as f, formatRfc9421SignatureParameters as i, signRequest as l, doubleKnock as n, parseRfc9421Signature as o, verifyRequestDetailed as p, formatRfc9421Signature as r, parseRfc9421SignatureInput as s, createRfc9421SignatureBase as t, timingSafeEqual as u };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-
|
|
6
|
-
import { c as
|
|
7
|
-
import { n as attachKeyOwnerEvidence, t as MAX_PORTABLE_KEY_TTL } from "./key-owner-evidence-
|
|
4
|
+
import { n as version, t as name } from "./deno-EopndaNb.mjs";
|
|
5
|
+
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-zMe834ID.mjs";
|
|
6
|
+
import { c as isPortableActorDocument, d as isPortableUri, l as isPortableId, m as parseKeyIdString, s as isCompatibleKeyId } from "./portable-key-id-Ca30-hOa.mjs";
|
|
7
|
+
import { n as attachKeyOwnerEvidence, t as MAX_PORTABLE_KEY_TTL } from "./key-owner-evidence-APB6NpSk.mjs";
|
|
8
8
|
import { getLogger } from "@logtape/logtape";
|
|
9
9
|
import { CryptographicKey, Multikey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
10
10
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import {
|
|
4
|
+
import { a as getRawCanonicalPortableId, c as isPortableActorDocument, n as getCanonicalPortableId } from "./portable-key-id-Ca30-hOa.mjs";
|
|
5
5
|
import { CryptographicKey, Object as Object$1 } from "@fedify/vocab";
|
|
6
6
|
//#region src/sig/key-owner-evidence.ts
|
|
7
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { t as MAX_PORTABLE_KEY_TTL } from "./key-owner-evidence-
|
|
4
|
+
import { t as MAX_PORTABLE_KEY_TTL } from "./key-owner-evidence-APB6NpSk.mjs";
|
|
5
5
|
import { CryptographicKey, Multikey } from "@fedify/vocab";
|
|
6
6
|
//#region src/federation/keycache.ts
|
|
7
7
|
const KEY_CACHE_GENERATION = "2";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import {
|
|
3
|
+
import { G as validateCryptoKey, ot as recordDocumentCache, t as doubleKnock } from "./http-BqN5kyUf.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
|
-
import { FetchError, UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
5
|
+
import { FetchError, UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, resolveDocumentLoaderTimeout, validatePublicUrl, withDocumentLoaderTimeout } from "@fedify/vocab-runtime";
|
|
6
6
|
import { curry } from "es-toolkit";
|
|
7
7
|
//#region src/utils/docloader.ts
|
|
8
8
|
const logger$1 = getLogger([
|
|
@@ -17,15 +17,19 @@ const DEFAULT_MAX_REDIRECTION = 20;
|
|
|
17
17
|
* the fetched documents.
|
|
18
18
|
* At most 20 HTTP redirects and alternate document links are followed in total
|
|
19
19
|
* per call. Revisiting a URL within that chain throws a {@link FetchError}.
|
|
20
|
+
* Each call, including its double-knocking retries, times out after
|
|
21
|
+
* 10 seconds by default; see {@link DocumentLoaderFactoryOptions.timeout}.
|
|
20
22
|
* @param identity The identity to get the document loader for.
|
|
21
23
|
* The actor's key pair.
|
|
22
24
|
* @param options The options for the document loader.
|
|
23
25
|
* @returns The authenticated document loader.
|
|
24
26
|
* @throws {TypeError} If the key is invalid or unsupported.
|
|
27
|
+
* @throws {RangeError} If the `timeout` option is invalid.
|
|
25
28
|
* @since 0.4.0
|
|
26
29
|
*/
|
|
27
|
-
function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, tracerProvider } = {}) {
|
|
30
|
+
function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, timeout, tracerProvider } = {}) {
|
|
28
31
|
validateCryptoKey(identity.privateKey);
|
|
32
|
+
const resolvedTimeout = resolveDocumentLoaderTimeout(timeout);
|
|
29
33
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
30
34
|
options?.signal?.throwIfAborted();
|
|
31
35
|
let currentUrl = new URL(url).href;
|
|
@@ -51,27 +55,31 @@ function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedi
|
|
|
51
55
|
currentUrl = nextUrl;
|
|
52
56
|
}
|
|
53
57
|
});
|
|
58
|
+
options?.signal?.throwIfAborted();
|
|
54
59
|
return getRemoteDocument(currentUrl, response, (alternateUrl) => {
|
|
55
60
|
follow(alternateUrl);
|
|
56
61
|
return load(alternateUrl, options, redirected, visited);
|
|
57
62
|
}, options);
|
|
58
63
|
}
|
|
59
64
|
async function validateUrl(url, options) {
|
|
60
|
-
if (!allowPrivateAddress)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
url,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
url,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
if (!allowPrivateAddress) {
|
|
66
|
+
try {
|
|
67
|
+
await validatePublicUrl(url);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (error instanceof UrlError) if (error.reason === "dns") logger$1.debug("DNS lookup failed for {url}", {
|
|
70
|
+
url,
|
|
71
|
+
error
|
|
72
|
+
});
|
|
73
|
+
else logger$1[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
74
|
+
url,
|
|
75
|
+
error
|
|
76
|
+
});
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
options?.signal?.throwIfAborted();
|
|
72
80
|
}
|
|
73
81
|
}
|
|
74
|
-
return (url, options) => load(url, options);
|
|
82
|
+
return withDocumentLoaderTimeout((url, options) => load(url, options), resolvedTimeout);
|
|
75
83
|
}
|
|
76
84
|
//#endregion
|
|
77
85
|
//#region src/utils/kv-cache.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { p as recordDocumentCache } from "./metrics-
|
|
4
|
+
import { p as recordDocumentCache } from "./metrics-zMe834ID.mjs";
|
|
5
5
|
import { getLogger } from "@logtape/logtape";
|
|
6
6
|
import { preloadedContexts } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/utils/kv-cache.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
|
-
const require_http = require("./http-
|
|
2
|
+
const require_http = require("./http-CCr2_ipG.cjs");
|
|
3
3
|
let _logtape_logtape = require("@logtape/logtape");
|
|
4
4
|
let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
|
|
5
5
|
let es_toolkit = require("es-toolkit");
|
|
@@ -16,15 +16,19 @@ const DEFAULT_MAX_REDIRECTION = 20;
|
|
|
16
16
|
* the fetched documents.
|
|
17
17
|
* At most 20 HTTP redirects and alternate document links are followed in total
|
|
18
18
|
* per call. Revisiting a URL within that chain throws a {@link FetchError}.
|
|
19
|
+
* Each call, including its double-knocking retries, times out after
|
|
20
|
+
* 10 seconds by default; see {@link DocumentLoaderFactoryOptions.timeout}.
|
|
19
21
|
* @param identity The identity to get the document loader for.
|
|
20
22
|
* The actor's key pair.
|
|
21
23
|
* @param options The options for the document loader.
|
|
22
24
|
* @returns The authenticated document loader.
|
|
23
25
|
* @throws {TypeError} If the key is invalid or unsupported.
|
|
26
|
+
* @throws {RangeError} If the `timeout` option is invalid.
|
|
24
27
|
* @since 0.4.0
|
|
25
28
|
*/
|
|
26
|
-
function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, tracerProvider } = {}) {
|
|
29
|
+
function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, timeout, tracerProvider } = {}) {
|
|
27
30
|
require_http.validateCryptoKey(identity.privateKey);
|
|
31
|
+
const resolvedTimeout = (0, _fedify_vocab_runtime.resolveDocumentLoaderTimeout)(timeout);
|
|
28
32
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
29
33
|
options?.signal?.throwIfAborted();
|
|
30
34
|
let currentUrl = new URL(url).href;
|
|
@@ -50,27 +54,31 @@ function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedi
|
|
|
50
54
|
currentUrl = nextUrl;
|
|
51
55
|
}
|
|
52
56
|
});
|
|
57
|
+
options?.signal?.throwIfAborted();
|
|
53
58
|
return (0, _fedify_vocab_runtime.getRemoteDocument)(currentUrl, response, (alternateUrl) => {
|
|
54
59
|
follow(alternateUrl);
|
|
55
60
|
return load(alternateUrl, options, redirected, visited);
|
|
56
61
|
}, options);
|
|
57
62
|
}
|
|
58
63
|
async function validateUrl(url, options) {
|
|
59
|
-
if (!allowPrivateAddress)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
url,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
url,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
if (!allowPrivateAddress) {
|
|
65
|
+
try {
|
|
66
|
+
await (0, _fedify_vocab_runtime.validatePublicUrl)(url);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
if (error instanceof _fedify_vocab_runtime.UrlError) if (error.reason === "dns") logger$1.debug("DNS lookup failed for {url}", {
|
|
69
|
+
url,
|
|
70
|
+
error
|
|
71
|
+
});
|
|
72
|
+
else logger$1[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
73
|
+
url,
|
|
74
|
+
error
|
|
75
|
+
});
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
options?.signal?.throwIfAborted();
|
|
71
79
|
}
|
|
72
80
|
}
|
|
73
|
-
return (url, options) => load(url, options);
|
|
81
|
+
return (0, _fedify_vocab_runtime.withDocumentLoaderTimeout)((url, options) => load(url, options), resolvedTimeout);
|
|
74
82
|
}
|
|
75
83
|
//#endregion
|
|
76
84
|
//#region src/utils/kv-cache.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-
|
|
6
|
-
import { c as validateCryptoKey, i as fetchKey, t as bypassKeyCacheReads } from "./key-
|
|
4
|
+
import { n as version, t as name } from "./deno-EopndaNb.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-zMe834ID.mjs";
|
|
6
|
+
import { c as validateCryptoKey, i as fetchKey, t as bypassKeyCacheReads } from "./key-DyXf88bq.mjs";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
|
|
9
9
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|