

























@@ -8,6 +8,10 @@ const CLAWHUB_PREFLIGHT_TIMEOUT_MS = readPositiveInt(
88process.env.OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_TIMEOUT_MS,
9930_000,
1010);
11+const CLAWHUB_PREFLIGHT_BODY_MAX_BYTES = readPositiveInt(
12+process.env.OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_BODY_MAX_BYTES,
13+1024 * 1024,
14+);
1115const readJson = (file) => JSON.parse(fs.readFileSync(file, "utf8"));
1216const scratchFile = (name) => path.join(scratchRoot, name);
1317@@ -42,6 +46,47 @@ async function withTimeout(label, timeoutMs, run) {
4246}
4347}
444849+function bodyTooLargeError(label, byteLimit) {
50+return Object.assign(new Error(`${label} response body exceeded ${byteLimit} bytes`), {
51+code: "ETOOBIG",
52+});
53+}
54+55+async function readBoundedResponseText(response, label, byteLimit) {
56+const contentLength = response.headers.get("content-length");
57+if (contentLength) {
58+const parsedLength = Number(contentLength);
59+if (Number.isSafeInteger(parsedLength) && parsedLength > byteLimit) {
60+await response.body?.cancel().catch(() => {});
61+throw bodyTooLargeError(label, byteLimit);
62+}
63+}
64+if (!response.body) {
65+return "";
66+}
67+68+const reader = response.body.getReader();
69+const decoder = new TextDecoder();
70+let byteCount = 0;
71+let text = "";
72+try {
73+while (true) {
74+const { done, value } = await reader.read();
75+if (done) {
76+return text + decoder.decode();
77+}
78+byteCount += value.byteLength;
79+if (byteCount > byteLimit) {
80+await reader.cancel().catch(() => {});
81+throw bodyTooLargeError(label, byteLimit);
82+}
83+text += decoder.decode(value, { stream: true });
84+}
85+} finally {
86+reader.releaseLock();
87+}
88+}
89+4590function resolveHomePath(value) {
4691if (value === "~") {
4792return process.env.HOME;
@@ -806,16 +851,31 @@ async function assertClawHubPreflight() {
806851const body = await withTimeout(
807852`ClawHub package preflight response for ${packageName}`,
808853CLAWHUB_PREFLIGHT_TIMEOUT_MS,
809-() => response.text().catch(() => ""),
854+() =>
855+readBoundedResponseText(
856+response,
857+`ClawHub package preflight response for ${packageName}`,
858+CLAWHUB_PREFLIGHT_BODY_MAX_BYTES,
859+),
810860);
811861throw new Error(
812862`ClawHub package preflight failed for ${packageName}: ${response.status} ${body}`,
813863);
814864}
815-const detail = await withTimeout(
865+const rawDetail = await withTimeout(
816866`ClawHub package preflight response for ${packageName}`,
817867CLAWHUB_PREFLIGHT_TIMEOUT_MS,
818-() => response.json(),
868+() =>
869+readBoundedResponseText(
870+response,
871+`ClawHub package preflight response for ${packageName}`,
872+CLAWHUB_PREFLIGHT_BODY_MAX_BYTES,
873+),
874+);
875+const detail = await withTimeout(
876+`ClawHub package preflight JSON for ${packageName}`,
877+CLAWHUB_PREFLIGHT_TIMEOUT_MS,
878+() => JSON.parse(rawDetail),
819879);
820880const family = detail.package?.family;
821881if (family !== "code-plugin" && family !== "bundle-plugin") {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。