fix(scripts): reject unsafe package download lengths · openclaw/openclaw@bb1043b
vincentkoc
·
2026-06-20
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -1209,7 +1209,10 @@ export async function downloadUrl(url, target, options = {}) {
|
1209 | 1209 | const rawContentLength = responseHeader(response, "content-length"); |
1210 | 1210 | const contentLength = |
1211 | 1211 | rawContentLength && /^\d+$/u.test(rawContentLength) ? Number(rawContentLength) : undefined; |
1212 | | -if (Number.isSafeInteger(contentLength) && contentLength > maxBytes) { |
| 1212 | +if ( |
| 1213 | +contentLength !== undefined && |
| 1214 | +(!Number.isSafeInteger(contentLength) || contentLength > maxBytes) |
| 1215 | +) { |
1213 | 1216 | throw new Error(`package_url exceeds maximum download size of ${maxBytes} bytes`); |
1214 | 1217 | } |
1215 | 1218 | await fs.rm(tempTarget, { force: true }); |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -726,6 +726,50 @@ describe("resolve-openclaw-package-candidate", () => {
|
726 | 726 | expect(bodyCancelled).toBe(true); |
727 | 727 | }); |
728 | 728 | |
| 729 | +it("rejects unsafe decimal package_url content-length values before reading", async () => { |
| 730 | +const dir = await mkdtemp(path.join(tmpdir(), "openclaw-package-download-")); |
| 731 | +tempDirs.push(dir); |
| 732 | +const target = path.join(dir, "openclaw.tgz"); |
| 733 | +let readStarted = false; |
| 734 | +let bodyCancelled = false; |
| 735 | + |
| 736 | +await expect( |
| 737 | +downloadUrl("https://packages.example/openclaw.tgz", target, { |
| 738 | +fetchImpl: async () => |
| 739 | +({ |
| 740 | +body: { |
| 741 | +cancel() { |
| 742 | +bodyCancelled = true; |
| 743 | +return Promise.resolve(); |
| 744 | +}, |
| 745 | +getReader() { |
| 746 | +return { |
| 747 | +cancel() { |
| 748 | +bodyCancelled = true; |
| 749 | +return Promise.resolve(); |
| 750 | +}, |
| 751 | +read() { |
| 752 | +readStarted = true; |
| 753 | +return new Promise(() => {}); |
| 754 | +}, |
| 755 | +releaseLock() {}, |
| 756 | +}; |
| 757 | +}, |
| 758 | +}, |
| 759 | +headers: new Headers({ "content-length": "9007199254740993" }), |
| 760 | +status: 200, |
| 761 | +}) as Response, |
| 762 | +lookupHost: lookupAddresses([{ address: "93.184.216.34", family: 4 }]), |
| 763 | +maxBytes: 1024, |
| 764 | +timeoutMs: 25, |
| 765 | +}), |
| 766 | +).rejects.toThrow(/exceeds maximum download size/u); |
| 767 | +expect(readStarted).toBe(false); |
| 768 | +expect(bodyCancelled).toBe(true); |
| 769 | +await expect(missing(target)).resolves.toBe(true); |
| 770 | +await expect(missing(`${target}.tmp`)).resolves.toBe(true); |
| 771 | +}); |
| 772 | + |
729 | 773 | it("bounds package_url downloads and writes completed files atomically", async () => { |
730 | 774 | const dir = await mkdtemp(path.join(tmpdir(), "openclaw-package-download-")); |
731 | 775 | tempDirs.push(dir); |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。