diff --git a/README.md b/README.md index 9f62511..979ac81 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ The no-secret preflight checks the target release is unused and verifies the previous catalog's exact downloaded bytes, detached signatures, and pinned public key. The credentialed build step resolves each private BOM commit and release tag exactly before the signing key is exposed. Archives are fail-closed on unsafe ZIP paths/metadata, -compression bombs, executable extras, missing source-package license metadata, and wrong PE +compression bombs, executable extras, and wrong PE platforms. ## Pull-request checks diff --git a/scripts/publish-catalog.mjs b/scripts/publish-catalog.mjs index aa24f44..665e88f 100644 --- a/scripts/publish-catalog.mjs +++ b/scripts/publish-catalog.mjs @@ -205,7 +205,6 @@ export async function inspectArchive(spec, archivePath, zipUtils, sequence) { try { manifest = JSON.parse(manifestEntry.data.toString("utf8")); } catch { fail(`${spec.id}: archive manifest.json is invalid JSON`); } requiredManifest(manifest, spec, spec.build?.provider ?? spec.id); const licenseEntry = files.find((entry) => /^license(?:[._-].*)?$/i.test(path.posix.basename(entry.name))); - if (spec.kind !== "app" && !licenseEntry && typeof manifest.license !== "string") fail(`${spec.id}: archive license is missing`); const expected = ["manifest.json", spec.entrypoint, spec.icon, ...(licenseEntry ? [licenseEntry.name] : [])].sort(); const actual = files.map((entry) => entry.name).sort(); if (spec.kind === "app" ? (expected.some((name) => !actual.includes(name)) || diff --git a/scripts/publish-catalog.test.mjs b/scripts/publish-catalog.test.mjs index c09dbc5..a2d5004 100644 --- a/scripts/publish-catalog.test.mjs +++ b/scripts/publish-catalog.test.mjs @@ -138,7 +138,7 @@ async function mutateCentral(file, entryName, mutate) { await writeFile(file, bytes); } -test("archive policy rejects traversal, collisions, missing license, and extra files", async () => { +test("archive policy rejects traversal, collisions, and extra files", async () => { const dir = await mkdtemp(path.join(tmpdir(), "kosmos-archive-")); try { const spec = archiveSpec(); @@ -159,14 +159,6 @@ test("archive policy rejects traversal, collisions, missing license, and extra f const extra = path.join(dir, "extra.kspkg"); await writeArchive(extra, spec, [{ name: "payload.exe", data: peFixture() }]); await assert.rejects(() => inspectArchive(spec, extra, { readZip }, 8), /unexpected/); - const noLicense = path.join(dir, "no-license.kspkg"); - const noLicenseSpec = { ...spec, artifact: { name: "no-license.kspkg" } }; - writeZip(noLicense, [ - { name: "manifest.json", data: JSON.stringify(completeManifest(noLicenseSpec)) }, - { name: noLicenseSpec.entrypoint, data: peFixture() }, - { name: noLicenseSpec.icon, data: Buffer.from("icon") }, - ]); - await assert.rejects(() => inspectArchive(noLicenseSpec, noLicense, { readZip }, 8), /license/); const traversal = path.join(dir, "traversal.kspkg"); await writeArchive(traversal, spec, [{ name: "../escape.txt", data: Buffer.from("x") }]); await assert.rejects(() => inspectArchive(spec, traversal, { readZip }, 8), /unsafe|unexpected/);