@fedify/vocab-runtime 2.0.33 → 2.0.34-dev.2423
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/deno.json +1 -1
- package/dist/mod.cjs +2 -1
- package/dist/mod.js +2 -1
- package/dist/tests/{body-Cjg7OBhe.cjs → body-Bf3IUKB-.cjs} +1 -1
- package/dist/tests/{body-CKUDh6i2.mjs → body-M8IeUMdL.mjs} +1 -1
- package/dist/tests/body.test.cjs +1 -1
- package/dist/tests/body.test.mjs +1 -1
- package/dist/tests/docloader.test.cjs +49 -2
- package/dist/tests/docloader.test.mjs +49 -2
- package/dist/tests/{request-zvoIOWWs.mjs → request-BS9N4kB1.mjs} +1 -1
- package/dist/tests/{request-BhX093Vd.cjs → request-Ds0hJGeF.cjs} +1 -1
- package/dist/tests/request.test.cjs +1 -1
- package/dist/tests/request.test.mjs +1 -1
- package/package.json +1 -1
- package/src/docloader.test.ts +84 -0
- package/src/docloader.ts +5 -0
package/deno.json
CHANGED
package/dist/mod.cjs
CHANGED
|
@@ -4504,7 +4504,7 @@ const preloadedContexts = {
|
|
|
4504
4504
|
//#endregion
|
|
4505
4505
|
//#region deno.json
|
|
4506
4506
|
var name = "@fedify/vocab-runtime";
|
|
4507
|
-
var version = "2.0.
|
|
4507
|
+
var version = "2.0.34-dev.2423+4999dc80";
|
|
4508
4508
|
//#endregion
|
|
4509
4509
|
//#region src/request.ts
|
|
4510
4510
|
/**
|
|
@@ -5160,6 +5160,7 @@ function getDocumentLoader({ allowPrivateAddress, skipPreloadedContexts, userAge
|
|
|
5160
5160
|
options?.signal?.throwIfAborted();
|
|
5161
5161
|
const parsedUrl = new URL(url);
|
|
5162
5162
|
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") throw new UrlError(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
5163
|
+
if (parsedUrl.username !== "" || parsedUrl.password !== "") throw new UrlError("URLs with credentials are not allowed");
|
|
5163
5164
|
const currentUrl = parsedUrl.href;
|
|
5164
5165
|
if (!skipPreloadedContexts && currentUrl in preloadedContexts) {
|
|
5165
5166
|
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|
package/dist/mod.js
CHANGED
|
@@ -4499,7 +4499,7 @@ const preloadedContexts = {
|
|
|
4499
4499
|
//#endregion
|
|
4500
4500
|
//#region deno.json
|
|
4501
4501
|
var name = "@fedify/vocab-runtime";
|
|
4502
|
-
var version = "2.0.
|
|
4502
|
+
var version = "2.0.34-dev.2423+4999dc80";
|
|
4503
4503
|
//#endregion
|
|
4504
4504
|
//#region src/request.ts
|
|
4505
4505
|
/**
|
|
@@ -5155,6 +5155,7 @@ function getDocumentLoader({ allowPrivateAddress, skipPreloadedContexts, userAge
|
|
|
5155
5155
|
options?.signal?.throwIfAborted();
|
|
5156
5156
|
const parsedUrl = new URL(url);
|
|
5157
5157
|
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") throw new UrlError(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
5158
|
+
if (parsedUrl.username !== "" || parsedUrl.password !== "") throw new UrlError("URLs with credentials are not allowed");
|
|
5158
5159
|
const currentUrl = parsedUrl.href;
|
|
5159
5160
|
if (!skipPreloadedContexts && currentUrl in preloadedContexts) {
|
|
5160
5161
|
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require("./chunk-Do9eywBl.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
2
|
+
const require_request = require("./request-Ds0hJGeF.cjs");
|
|
3
3
|
let _logtape_logtape = require("@logtape/logtape");
|
|
4
4
|
//#region src/body.ts
|
|
5
5
|
/** Decoded JSON body limit: 16 MiB. @internal */
|
package/dist/tests/body.test.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require("./chunk-Do9eywBl.cjs");
|
|
2
|
-
const require_body = require("./body-
|
|
2
|
+
const require_body = require("./body-Bf3IUKB-.cjs");
|
|
3
3
|
let node_assert_strict = require("node:assert/strict");
|
|
4
4
|
let node_test = require("node:test");
|
|
5
5
|
let node_zlib = require("node:zlib");
|
package/dist/tests/body.test.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as readBoundedText, t as BodyTooLargeError } from "./body-
|
|
1
|
+
import { r as readBoundedText, t as BodyTooLargeError } from "./body-M8IeUMdL.mjs";
|
|
2
2
|
import { deepStrictEqual, ok, rejects } from "node:assert/strict";
|
|
3
3
|
import { test } from "node:test";
|
|
4
4
|
import { gunzipSync, gzipSync } from "node:zlib";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-Do9eywBl.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
3
|
-
const require_body = require("./body-
|
|
2
|
+
const require_request = require("./request-Ds0hJGeF.cjs");
|
|
3
|
+
const require_body = require("./body-Bf3IUKB-.cjs");
|
|
4
4
|
const require_link = require("./link-FguCydMA.cjs");
|
|
5
5
|
const require_url = require("./url-Qk1svKZU.cjs");
|
|
6
6
|
let node_zlib = require("node:zlib");
|
|
@@ -5826,6 +5826,7 @@ function getDocumentLoader({ allowPrivateAddress, skipPreloadedContexts, userAge
|
|
|
5826
5826
|
options?.signal?.throwIfAborted();
|
|
5827
5827
|
const parsedUrl = new URL(url);
|
|
5828
5828
|
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") throw new require_url.UrlError(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
5829
|
+
if (parsedUrl.username !== "" || parsedUrl.password !== "") throw new require_url.UrlError("URLs with credentials are not allowed");
|
|
5829
5830
|
const currentUrl = parsedUrl.href;
|
|
5830
5831
|
if (!skipPreloadedContexts && currentUrl in preloadedContexts) {
|
|
5831
5832
|
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|
|
@@ -6696,6 +6697,52 @@ const unsupportedUrls = [
|
|
|
6696
6697
|
"file:///collection",
|
|
6697
6698
|
`data:application/ld+json,${encodeURIComponent(JSON.stringify({ id: "https://example.com/data" }))}`
|
|
6698
6699
|
];
|
|
6700
|
+
function isCredentialUrlError(error) {
|
|
6701
|
+
return error instanceof require_url.UrlError && error.reason === "disallowed" && error.message === "URLs with credentials are not allowed";
|
|
6702
|
+
}
|
|
6703
|
+
(0, _fedify_fixture.test)("getDocumentLoader() rejects URLs with credentials", async (t) => {
|
|
6704
|
+
const start = "https://8.8.8.8/start";
|
|
6705
|
+
const target = "https://user:pass@8.8.8.8/document";
|
|
6706
|
+
for (const allowPrivateAddress of [false, true]) {
|
|
6707
|
+
const loader = getDocumentLoader({ allowPrivateAddress });
|
|
6708
|
+
for (const path of [
|
|
6709
|
+
"direct",
|
|
6710
|
+
"redirect",
|
|
6711
|
+
"Link",
|
|
6712
|
+
"HTML"
|
|
6713
|
+
]) await t.step(`${path}, allowPrivateAddress=${allowPrivateAddress}`, async () => {
|
|
6714
|
+
await withFetchStub((url) => {
|
|
6715
|
+
if (url !== start) return Response.json({});
|
|
6716
|
+
if (path === "redirect") return Response.redirect(target, 302);
|
|
6717
|
+
if (path === "HTML") return new Response(`<link rel="alternate" type="application/activity+json" href="${target}">`, { headers: { "Content-Type": "text/html" } });
|
|
6718
|
+
return new Response("", { headers: {
|
|
6719
|
+
"Content-Type": "text/plain",
|
|
6720
|
+
Link: `<${target}>; rel="alternate"; type="application/activity+json"`
|
|
6721
|
+
} });
|
|
6722
|
+
}, async (fetched) => {
|
|
6723
|
+
await (0, node_assert.rejects)(loader(path === "direct" ? target : start), isCredentialUrlError);
|
|
6724
|
+
(0, node_assert.deepStrictEqual)(fetched, path === "direct" ? [] : [start]);
|
|
6725
|
+
});
|
|
6726
|
+
});
|
|
6727
|
+
for (const url of [
|
|
6728
|
+
"https://user@8.8.8.8/document",
|
|
6729
|
+
"https://:pass@8.8.8.8/document",
|
|
6730
|
+
"https://%75ser:p%40ss@8.8.8.8/document",
|
|
6731
|
+
"http://user:pass@8.8.8.8/document"
|
|
6732
|
+
]) await t.step(`${url}, allowPrivateAddress=${allowPrivateAddress}`, async () => {
|
|
6733
|
+
await withFetchStub(() => Response.json({}), async (fetched) => {
|
|
6734
|
+
await (0, node_assert.rejects)(loader(url), isCredentialUrlError);
|
|
6735
|
+
(0, node_assert.deepStrictEqual)(fetched, []);
|
|
6736
|
+
});
|
|
6737
|
+
});
|
|
6738
|
+
for (const url of ["https://:@8.8.8.8/document", "https://8.8.8.8/@user?q=@pass"]) await t.step(`allows ${url}, allowPrivateAddress=${allowPrivateAddress}`, async () => {
|
|
6739
|
+
await withFetchStub(() => Response.json({ done: true }), async (fetched) => {
|
|
6740
|
+
(0, node_assert.deepStrictEqual)((await loader(url)).document, { done: true });
|
|
6741
|
+
(0, node_assert.deepStrictEqual)(fetched, [new URL(url).href]);
|
|
6742
|
+
});
|
|
6743
|
+
});
|
|
6744
|
+
}
|
|
6745
|
+
});
|
|
6699
6746
|
function isUnsupportedProtocolError(error, url) {
|
|
6700
6747
|
return error instanceof require_url.UrlError && error.message === `Unsupported protocol: ${new URL(url).protocol}` && error.reason === "disallowed";
|
|
6701
6748
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as name, i as logRequest, n as createActivityPubRequest, o as version, t as FetchError } from "./request-
|
|
2
|
-
import { n as MAX_BODY_SIZE, r as readBoundedText } from "./body-
|
|
1
|
+
import { a as name, i as logRequest, n as createActivityPubRequest, o as version, t as FetchError } from "./request-BS9N4kB1.mjs";
|
|
2
|
+
import { n as MAX_BODY_SIZE, r as readBoundedText } from "./body-M8IeUMdL.mjs";
|
|
3
3
|
import { t as HttpHeaderLink } from "./link-NUUWCdnK.mjs";
|
|
4
4
|
import { o as validatePublicUrl, t as UrlError } from "./url-DzlMS01z.mjs";
|
|
5
5
|
import { gzipSync } from "node:zlib";
|
|
@@ -5843,6 +5843,7 @@ function getDocumentLoader({ allowPrivateAddress, skipPreloadedContexts, userAge
|
|
|
5843
5843
|
options?.signal?.throwIfAborted();
|
|
5844
5844
|
const parsedUrl = new URL(url);
|
|
5845
5845
|
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") throw new UrlError(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
5846
|
+
if (parsedUrl.username !== "" || parsedUrl.password !== "") throw new UrlError("URLs with credentials are not allowed");
|
|
5846
5847
|
const currentUrl = parsedUrl.href;
|
|
5847
5848
|
if (!skipPreloadedContexts && currentUrl in preloadedContexts) {
|
|
5848
5849
|
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|
|
@@ -6713,6 +6714,52 @@ const unsupportedUrls = [
|
|
|
6713
6714
|
"file:///collection",
|
|
6714
6715
|
`data:application/ld+json,${encodeURIComponent(JSON.stringify({ id: "https://example.com/data" }))}`
|
|
6715
6716
|
];
|
|
6717
|
+
function isCredentialUrlError(error) {
|
|
6718
|
+
return error instanceof UrlError && error.reason === "disallowed" && error.message === "URLs with credentials are not allowed";
|
|
6719
|
+
}
|
|
6720
|
+
test("getDocumentLoader() rejects URLs with credentials", async (t) => {
|
|
6721
|
+
const start = "https://8.8.8.8/start";
|
|
6722
|
+
const target = "https://user:pass@8.8.8.8/document";
|
|
6723
|
+
for (const allowPrivateAddress of [false, true]) {
|
|
6724
|
+
const loader = getDocumentLoader({ allowPrivateAddress });
|
|
6725
|
+
for (const path of [
|
|
6726
|
+
"direct",
|
|
6727
|
+
"redirect",
|
|
6728
|
+
"Link",
|
|
6729
|
+
"HTML"
|
|
6730
|
+
]) await t.step(`${path}, allowPrivateAddress=${allowPrivateAddress}`, async () => {
|
|
6731
|
+
await withFetchStub((url) => {
|
|
6732
|
+
if (url !== start) return Response.json({});
|
|
6733
|
+
if (path === "redirect") return Response.redirect(target, 302);
|
|
6734
|
+
if (path === "HTML") return new Response(`<link rel="alternate" type="application/activity+json" href="${target}">`, { headers: { "Content-Type": "text/html" } });
|
|
6735
|
+
return new Response("", { headers: {
|
|
6736
|
+
"Content-Type": "text/plain",
|
|
6737
|
+
Link: `<${target}>; rel="alternate"; type="application/activity+json"`
|
|
6738
|
+
} });
|
|
6739
|
+
}, async (fetched) => {
|
|
6740
|
+
await rejects(loader(path === "direct" ? target : start), isCredentialUrlError);
|
|
6741
|
+
deepStrictEqual(fetched, path === "direct" ? [] : [start]);
|
|
6742
|
+
});
|
|
6743
|
+
});
|
|
6744
|
+
for (const url of [
|
|
6745
|
+
"https://user@8.8.8.8/document",
|
|
6746
|
+
"https://:pass@8.8.8.8/document",
|
|
6747
|
+
"https://%75ser:p%40ss@8.8.8.8/document",
|
|
6748
|
+
"http://user:pass@8.8.8.8/document"
|
|
6749
|
+
]) await t.step(`${url}, allowPrivateAddress=${allowPrivateAddress}`, async () => {
|
|
6750
|
+
await withFetchStub(() => Response.json({}), async (fetched) => {
|
|
6751
|
+
await rejects(loader(url), isCredentialUrlError);
|
|
6752
|
+
deepStrictEqual(fetched, []);
|
|
6753
|
+
});
|
|
6754
|
+
});
|
|
6755
|
+
for (const url of ["https://:@8.8.8.8/document", "https://8.8.8.8/@user?q=@pass"]) await t.step(`allows ${url}, allowPrivateAddress=${allowPrivateAddress}`, async () => {
|
|
6756
|
+
await withFetchStub(() => Response.json({ done: true }), async (fetched) => {
|
|
6757
|
+
deepStrictEqual((await loader(url)).document, { done: true });
|
|
6758
|
+
deepStrictEqual(fetched, [new URL(url).href]);
|
|
6759
|
+
});
|
|
6760
|
+
});
|
|
6761
|
+
}
|
|
6762
|
+
});
|
|
6716
6763
|
function isUnsupportedProtocolError(error, url) {
|
|
6717
6764
|
return error instanceof UrlError && error.message === `Unsupported protocol: ${new URL(url).protocol}` && error.reason === "disallowed";
|
|
6718
6765
|
}
|
|
@@ -3,7 +3,7 @@ let node_process = require("node:process");
|
|
|
3
3
|
node_process = require_chunk.__toESM(node_process);
|
|
4
4
|
//#region deno.json
|
|
5
5
|
var name = "@fedify/vocab-runtime";
|
|
6
|
-
var version = "2.0.
|
|
6
|
+
var version = "2.0.34-dev.2423+4999dc80";
|
|
7
7
|
//#endregion
|
|
8
8
|
//#region src/request.ts
|
|
9
9
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-Do9eywBl.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
2
|
+
const require_request = require("./request-Ds0hJGeF.cjs");
|
|
3
3
|
let node_test = require("node:test");
|
|
4
4
|
let node_process = require("node:process");
|
|
5
5
|
node_process = require_chunk.__toESM(node_process);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { o as version, r as getUserAgent } from "./request-
|
|
1
|
+
import { o as version, r as getUserAgent } from "./request-BS9N4kB1.mjs";
|
|
2
2
|
import { test } from "node:test";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { deepStrictEqual } from "node:assert";
|
package/package.json
CHANGED
package/src/docloader.test.ts
CHANGED
|
@@ -1093,6 +1093,90 @@ const unsupportedUrls = [
|
|
|
1093
1093
|
}`,
|
|
1094
1094
|
];
|
|
1095
1095
|
|
|
1096
|
+
function isCredentialUrlError(error: unknown): boolean {
|
|
1097
|
+
return error instanceof UrlError && error.reason === "disallowed" &&
|
|
1098
|
+
error.message === "URLs with credentials are not allowed";
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
test("getDocumentLoader() rejects URLs with credentials", async (t) => {
|
|
1102
|
+
const start = "https://8.8.8.8/start";
|
|
1103
|
+
const target = "https://user:pass@8.8.8.8/document";
|
|
1104
|
+
for (const allowPrivateAddress of [false, true]) {
|
|
1105
|
+
const loader = getDocumentLoader({ allowPrivateAddress });
|
|
1106
|
+
for (const path of ["direct", "redirect", "Link", "HTML"]) {
|
|
1107
|
+
await t.step(
|
|
1108
|
+
`${path}, allowPrivateAddress=${allowPrivateAddress}`,
|
|
1109
|
+
async () => {
|
|
1110
|
+
await withFetchStub(
|
|
1111
|
+
(url) => {
|
|
1112
|
+
if (url !== start) return Response.json({});
|
|
1113
|
+
if (path === "redirect") return Response.redirect(target, 302);
|
|
1114
|
+
if (path === "HTML") {
|
|
1115
|
+
return new Response(
|
|
1116
|
+
`<link rel="alternate" type="application/activity+json" href="${target}">`,
|
|
1117
|
+
{ headers: { "Content-Type": "text/html" } },
|
|
1118
|
+
);
|
|
1119
|
+
}
|
|
1120
|
+
return new Response("", {
|
|
1121
|
+
headers: {
|
|
1122
|
+
"Content-Type": "text/plain",
|
|
1123
|
+
Link:
|
|
1124
|
+
`<${target}>; rel="alternate"; type="application/activity+json"`,
|
|
1125
|
+
},
|
|
1126
|
+
});
|
|
1127
|
+
},
|
|
1128
|
+
async (fetched) => {
|
|
1129
|
+
await rejects(
|
|
1130
|
+
loader(path === "direct" ? target : start),
|
|
1131
|
+
isCredentialUrlError,
|
|
1132
|
+
);
|
|
1133
|
+
deepStrictEqual(fetched, path === "direct" ? [] : [start]);
|
|
1134
|
+
},
|
|
1135
|
+
);
|
|
1136
|
+
},
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
1139
|
+
for (
|
|
1140
|
+
const url of [
|
|
1141
|
+
"https://user@8.8.8.8/document",
|
|
1142
|
+
"https://:pass@8.8.8.8/document",
|
|
1143
|
+
"https://%75ser:p%40ss@8.8.8.8/document",
|
|
1144
|
+
"http://user:pass@8.8.8.8/document",
|
|
1145
|
+
]
|
|
1146
|
+
) {
|
|
1147
|
+
await t.step(
|
|
1148
|
+
`${url}, allowPrivateAddress=${allowPrivateAddress}`,
|
|
1149
|
+
async () => {
|
|
1150
|
+
await withFetchStub(() => Response.json({}), async (fetched) => {
|
|
1151
|
+
await rejects(loader(url), isCredentialUrlError);
|
|
1152
|
+
deepStrictEqual(fetched, []);
|
|
1153
|
+
});
|
|
1154
|
+
},
|
|
1155
|
+
);
|
|
1156
|
+
}
|
|
1157
|
+
for (
|
|
1158
|
+
const url of [
|
|
1159
|
+
"https://:@8.8.8.8/document",
|
|
1160
|
+
"https://8.8.8.8/@user?q=@pass",
|
|
1161
|
+
]
|
|
1162
|
+
) {
|
|
1163
|
+
await t.step(
|
|
1164
|
+
`allows ${url}, allowPrivateAddress=${allowPrivateAddress}`,
|
|
1165
|
+
async () => {
|
|
1166
|
+
await withFetchStub(
|
|
1167
|
+
() => Response.json({ done: true }),
|
|
1168
|
+
async (fetched) => {
|
|
1169
|
+
const document = await loader(url);
|
|
1170
|
+
deepStrictEqual(document.document, { done: true });
|
|
1171
|
+
deepStrictEqual(fetched, [new URL(url).href]);
|
|
1172
|
+
},
|
|
1173
|
+
);
|
|
1174
|
+
},
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1179
|
+
|
|
1096
1180
|
function isUnsupportedProtocolError(error: unknown, url: string): boolean {
|
|
1097
1181
|
return error instanceof UrlError &&
|
|
1098
1182
|
error.message === `Unsupported protocol: ${new URL(url).protocol}` &&
|
package/src/docloader.ts
CHANGED
|
@@ -306,6 +306,11 @@ export function getDocumentLoader(
|
|
|
306
306
|
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
|
|
307
307
|
throw new UrlError(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
308
308
|
}
|
|
309
|
+
// When merging forward, keep this guard independent of allowPrivateAddress:
|
|
310
|
+
// private-address opt-in must not permit credentials on any followed URL.
|
|
311
|
+
if (parsedUrl.username !== "" || parsedUrl.password !== "") {
|
|
312
|
+
throw new UrlError("URLs with credentials are not allowed");
|
|
313
|
+
}
|
|
309
314
|
const currentUrl = parsedUrl.href;
|
|
310
315
|
if (!skipPreloadedContexts && currentUrl in preloadedContexts) {
|
|
311
316
|
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|