From 325ede1bc1dc2a8bc2095f5a556cbf07d206ccea Mon Sep 17 00:00:00 2001 From: Joseph Yaksich Date: Sat, 1 Aug 2026 22:32:35 +0000 Subject: [PATCH] fix: fail closed on invalid Linux package roots --- CHANGELOG.md | 4 ++++ scripts/package-linux-host.mjs | 18 ++++++++++++++++++ test/connectors.mjs | 23 ++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e131e7f..867282f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 playbooks active in every resident turn so imperative setup requests are executed instead of answered with tutorials, and evidenced machine-wide network failures are escalated directly for repair. +- Made Linux release packaging fail closed unless it runs in the exact Git + checkout whose `HEAD` contains the advertised version and a complete source + archive, preventing a nested source copy from silently packaging only sealed + runtime assets from a parent repository. ## [0.0.34] - 2026-08-01 diff --git a/scripts/package-linux-host.mjs b/scripts/package-linux-host.mjs index 9d49956..20ce396 100755 --- a/scripts/package-linux-host.mjs +++ b/scripts/package-linux-host.mjs @@ -27,6 +27,18 @@ const sealed = [ "container/channel-machine.oci.sha256", "container/channel-machine.oci.json", ]; + +const repository = spawnSync("git", ["rev-parse", "--show-toplevel"], { cwd: root, encoding: "utf8" }); +const repositoryRoot = repository.status === 0 ? resolve(String(repository.stdout || "").trim()) : ""; +if (repositoryRoot !== root) { + throw new Error("Linux packaging must run from the root of the exact Git checkout; a parent repository or source copy is not release authority"); +} +const headPackage = spawnSync("git", ["show", "HEAD:package.json"], { cwd: root, encoding: "utf8" }); +let headVersion = ""; +try { headVersion = String(JSON.parse(String(headPackage.stdout || "{}")).version || "").trim(); } catch { } +if (headPackage.status !== 0 || headVersion !== version) { + throw new Error("Linux packaging version does not match package.json at Git HEAD"); +} for (const rel of sealed.slice(0, 2)) { if (!existsSync(resolve(root, rel))) { throw new Error(`Linux packaging requires the sealed channel image at ${rel} (run scripts/build-oci-channel-image.sh on a builder host).`); @@ -45,9 +57,15 @@ try { maxBuffer: 512 * 1024 * 1024, }); if (archive.status !== 0) throw new Error("Could not package the exact Git release source"); + if (!archive.stdout?.length) throw new Error("Exact Git release source archive was empty"); const extract = spawnSync("tar", ["-xf", "-", "-C", stage], { input: archive.stdout, stdio: ["pipe", "inherit", "inherit"] }); if (extract.status !== 0) throw new Error("Could not extract the Git release source for packaging"); + const stagedPackage = resolve(stage, prefix, "package.json"); + if (!existsSync(stagedPackage) || String(JSON.parse(readFileSync(stagedPackage, "utf8")).version || "") !== version) { + throw new Error("Exact Git release source archive is missing its versioned package contract"); + } + const containerDir = join(stage, prefix, "container"); mkdirSync(containerDir, { recursive: true }); for (const rel of sealed) { diff --git a/test/connectors.mjs b/test/connectors.mjs index b25dabf..e674940 100644 --- a/test/connectors.mjs +++ b/test/connectors.mjs @@ -1,8 +1,9 @@ import assert from "node:assert/strict"; -import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; +import { chmod, copyFile, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; import { readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; +import { spawnSync } from "node:child_process"; import test from "node:test"; test("Linux release packaging ships pinned connectors for every supported host architecture", () => { @@ -16,10 +17,30 @@ test("Linux release packaging ships pinned connectors for every supported host a } assert.match(packageLinux, /cloudflared-linux-\$\{connector\.arch\}/, "the verified binaries enter the Linux release archive"); assert.match(packageLinux, /chmodSync\(destination, 0o755\)/, "packaged Linux connectors retain executable mode"); + assert.match(packageLinux, /rev-parse[\s\S]*--show-toplevel[\s\S]*repositoryRoot !== root[\s\S]*parent repository or source copy is not release authority/, "Linux packaging fails closed when a copied source tree accidentally resolves to a parent Git checkout"); + assert.match(packageLinux, /git", \["show", "HEAD:package\.json"\][\s\S]*headVersion !== version/, "Linux packaging binds its visible version to the exact Git HEAD"); + assert.match(packageLinux, /archive\.stdout\?\.length[\s\S]*stagedPackage[\s\S]*versioned package contract/, "Linux packaging rejects an empty or structurally incomplete Git source archive"); assert.match(resolver, /cloudflared-linux-\$\{process\.arch\}/, "Linux resolves only the binary matching the running host architecture"); assert.match(resolver, /process\.env\.HELM_APP_ROOT[\s\S]*process\.cwd\(\)/, "an installed Linux service can resolve its bundled connector from its release working directory"); }); +test("Linux release packaging rejects a source copy nested under another Git checkout", async () => { + const projectRoot = join(import.meta.dirname, ".."); + const version = JSON.parse(readFileSync(join(projectRoot, "package.json"), "utf8")).version; + const copiedRoot = await mkdtemp(join(projectRoot, ".package-root-test-")); + const copiedScripts = join(copiedRoot, "scripts"); + await mkdir(copiedScripts); + await copyFile(join(projectRoot, "scripts", "package-linux-host.mjs"), join(copiedScripts, "package-linux-host.mjs")); + await writeFile(join(copiedRoot, "package.json"), `${JSON.stringify({ version })}\n`); + try { + const result = spawnSync(process.execPath, [join(copiedScripts, "package-linux-host.mjs")], { cwd: copiedRoot, encoding: "utf8" }); + assert.notEqual(result.status, 0); + assert.match(`${result.stdout}\n${result.stderr}`, /parent repository or source copy is not release authority/); + } finally { + await rm(copiedRoot, { recursive: true, force: true }); + } +}); + test("Linux service working directory resolves the bundled connector without a legacy app-root environment", async (t) => { if (process.platform !== "linux") { t.skip("Linux systemd working-directory contract");