From 099fd494089598334190be68e055734bde3ec80c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 08:16:05 +0000 Subject: [PATCH] fix: validate Content-Type and size for LFS PDF download (alert #636) Add response Content-Type validation and a 50 MB size limit to the network-to-file path in ensure-docs-slide-pdf.js, addressing the js/http-to-file-access CodeQL alert (#636). Changes: - Reject responses whose Content-Type is not application/pdf or application/octet-stream before reading the body. - Enforce a 50 MB ceiling via both the Content-Length header (early rejection) and the actual downloaded byte count (double-check). - The existing PDF magic-bytes check (isPdf) is preserved as a third layer of validation. - All new checks throw errors that are caught by the surrounding try/catch block, so the script still falls back to the placeholder PDF rather than crashing in sandboxed environments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- scripts/ensure-docs-slide-pdf.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/scripts/ensure-docs-slide-pdf.js b/scripts/ensure-docs-slide-pdf.js index 367bf6014de..e977fa52e28 100644 --- a/scripts/ensure-docs-slide-pdf.js +++ b/scripts/ensure-docs-slide-pdf.js @@ -112,7 +112,25 @@ async function readPdfBytes() { throw new Error(`Failed to download slide deck PDF: ${response.status} ${response.statusText}`); } + // Validate the Content-Type header before consuming the body to ensure we + // are actually receiving a PDF and not arbitrary data. + const contentType = response.headers.get("content-type") ?? ""; + if (!contentType.startsWith("application/pdf") && !contentType.startsWith("application/octet-stream")) { + throw new Error(`Unexpected content-type for slide deck: ${contentType}`); + } + + // Guard against unexpectedly large downloads. + const MAX_BYTES = 50 * 1024 * 1024; // 50 MB + const contentLength = response.headers.get("content-length"); + if (contentLength !== null && Number(contentLength) > MAX_BYTES) { + throw new Error(`Slide deck download size ${contentLength} exceeds limit of ${MAX_BYTES} bytes`); + } + const downloadedBytes = Buffer.from(await response.arrayBuffer()); + if (downloadedBytes.length > MAX_BYTES) { + throw new Error(`Downloaded slide deck size ${downloadedBytes.length} exceeds limit of ${MAX_BYTES} bytes`); + } + if (!isPdf(downloadedBytes)) { throw new Error(`Downloaded slide deck from ${url} is not a real PDF.`); }