From 4e4c5d113db0fee1132216f34d711bd8b230ae2e Mon Sep 17 00:00:00 2001 From: Jeff <158072326+jeffrey701@users.noreply.github.com> Date: Fri, 24 Jul 2026 16:18:13 +0200 Subject: [PATCH] fix(scenarios): reject non-array changedFiles that bypasses the source-upload scan --- src/scenarios/input-model.ts | 7 +++++++ test/unit/scenario-input-model.test.ts | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/scenarios/input-model.ts b/src/scenarios/input-model.ts index 6ea6afa61c..6677223dc8 100644 --- a/src/scenarios/input-model.ts +++ b/src/scenarios/input-model.ts @@ -196,6 +196,13 @@ export function assertScenarioLocalBranchInputSafe(payload: Record { ).not.toThrow(); }); + it("rejects a present-but-non-array changedFiles that would otherwise bypass the source scan (#8328)", () => { + // A plain object like { diff: "…source…" } or a bare string is not the documented array-of-entries shape; + // before #8328 the Array.isArray guard silently skipped the forbidden-key/oversize scan for these values, + // letting exactly the source content this validator refuses slip through unchecked. + expect(() => assertScenarioLocalBranchInputSafe({ changedFiles: { diff: "x".repeat(5000) } })).toThrow(/non-array changedFiles/i); + expect(() => assertScenarioLocalBranchInputSafe({ changedFiles: "not-an-array" })).toThrow(/non-array changedFiles/i); + // The existing valid shapes (a real array, an omitted changedFiles) must still be accepted unchanged. + expect(() => assertScenarioLocalBranchInputSafe({ changedFiles: [{ path: "ok.ts" }] })).not.toThrow(); + expect(() => assertScenarioLocalBranchInputSafe({ login: "miner", repoFullName: "octo/demo" })).not.toThrow(); + }); + it("rejects source-upload env flag and forbidden local branch keys", () => { const previous = process.env.LOOPOVER_UPLOAD_SOURCE; process.env.LOOPOVER_UPLOAD_SOURCE = "true";