fix(infra): cap ClawHub install-resolution JSON via shared bounded re… · openclaw/openclaw@31f1ce1
Alix-007
·
2026-06-24
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -854,6 +854,42 @@ describe("clawhub helpers", () => {
|
854 | 854 | expect(message.length).toBeLessThanOrEqual(500); |
855 | 855 | }); |
856 | 856 | |
| 857 | +it("bounds oversized ClawHub install-resolution JSON responses and cancels the stream", async () => { |
| 858 | +const cancel = vi.fn(); |
| 859 | +const chunk = new Uint8Array(512 * 1024).fill("x".charCodeAt(0)); |
| 860 | +const overshootChunks = 34; // 34 * 512 KiB = 17 MiB > 16 MiB cap |
| 861 | +let emitted = 0; |
| 862 | +const body = new ReadableStream<Uint8Array>({ |
| 863 | +pull(controller) { |
| 864 | +if (emitted >= overshootChunks) { |
| 865 | +controller.close(); |
| 866 | +return; |
| 867 | +} |
| 868 | +emitted += 1; |
| 869 | +controller.enqueue(chunk); |
| 870 | +}, |
| 871 | +cancel() { |
| 872 | +cancel(); |
| 873 | +}, |
| 874 | +}); |
| 875 | + |
| 876 | +await expect( |
| 877 | +fetchClawHubSkillInstallResolution({ |
| 878 | +slug: "weather", |
| 879 | +fetchImpl: async () => |
| 880 | +new Response(body, { |
| 881 | +status: 200, |
| 882 | +headers: { "content-type": "application/json" }, |
| 883 | +}), |
| 884 | +}), |
| 885 | +).rejects.toThrow( |
| 886 | +/ClawHub \/api\/v1\/skills\/weather\/install response exceeded 16777216 bytes/, |
| 887 | +); |
| 888 | +// Same bounded reader covers the sibling install-resolution JSON path so a |
| 889 | +// hostile install response cannot exhaust memory either. |
| 890 | +expect(cancel).toHaveBeenCalledTimes(1); |
| 891 | +}); |
| 892 | + |
857 | 893 | it("annotates 429 errors with the reset hint but no sign-in hint when authenticated", async () => { |
858 | 894 | process.env.OPENCLAW_CLAWHUB_TOKEN = "env-token-123"; |
859 | 895 | await expect( |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -1018,11 +1018,7 @@ export async function fetchClawHubSkillInstallResolution(params: {
|
1018 | 1018 | if (!response.ok && !isStructuredBlock) { |
1019 | 1019 | throw await buildClawHubError(response, url, hasToken); |
1020 | 1020 | } |
1021 | | -try { |
1022 | | -return (await response.json()) as ClawHubSkillInstallResolutionResponse; |
1023 | | -} catch (cause) { |
1024 | | -throw new Error(`ClawHub ${url.pathname} returned malformed JSON`, { cause }); |
1025 | | -} |
| 1021 | +return parseClawHubJsonBody<ClawHubSkillInstallResolutionResponse>(response, url); |
1026 | 1022 | } |
1027 | 1023 | |
1028 | 1024 | export async function fetchClawHubSkillVerification(params: { |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。