fix(artifacts): compare package signatures without ASCII folding (#2069)

This commit is contained in:
xin zhuang 2026-10-12 15:18:03 +08:00 committed by GitHub
parent b3dec005bc
commit 75a4a14fa0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 39 additions and 4 deletions

View File

@ -299,7 +299,7 @@ const detectArtifactFormat = async (
if (
lower.endsWith(".pkg") &&
observed.bytesRead >= 4 &&
magic.subarray(0, 4).toString("ascii") === "xar!"
magic.subarray(0, 4).equals(Buffer.from("xar!"))
)
return "pkg";
if (lower.endsWith(".dmg")) {
@ -310,7 +310,7 @@ const detectArtifactFormat = async (
const trailer = Buffer.alloc(4);
const read = await handle.read(trailer, 0, trailer.length, size - 512);
throwIfTargetResolutionCancelled(signal);
if (read.bytesRead === 4 && trailer.toString("ascii") === "koly")
if (read.bytesRead === 4 && trailer.equals(Buffer.from("koly")))
return "dmg";
}
}

View File

@ -152,7 +152,7 @@ const classifyRootFormat = async (
if (hasZipSignature(prefix)) return zipRootPackageFormat(lower);
if (
lower.endsWith(".pkg") &&
prefix.subarray(0, 4).toString("ascii") === "xar!"
prefix.subarray(0, 4).equals(Buffer.from("xar!"))
)
return "pkg";
if (lower.endsWith(".dmg") && (await hasKolyTrailer(handle))) return "dmg";
@ -172,5 +172,5 @@ const hasKolyTrailer = async (handle: FileHandle): Promise<boolean> => {
if (size < 512) return false;
const trailer = Buffer.alloc(4);
const read = await handle.read(trailer, 0, trailer.length, size - 512);
return read.bytesRead === 4 && trailer.toString("ascii") === "koly";
return read.bytesRead === 4 && trailer.equals(Buffer.from("koly"));
};

View File

@ -199,3 +199,38 @@ describe("nested container family", () => {
},
);
});
describe("package signature byte identity", () => {
it.each([
{ extension: "pkg", signature: "xar!", offset: 0, size: 4 },
{ extension: "dmg", signature: "koly", offset: 0, size: 512 },
])(
"rejects high-bit aliases of $extension magic at both admission boundaries",
async ({ extension, signature, offset, size }) => {
const root = await createTestTempDirectory("rea-package-magic-");
const path = join(root, `input.${extension}`);
const bytes = Buffer.alloc(size);
bytes.write(signature, offset, "ascii");
await writeFile(path, bytes);
expect(
(await classifyAndHashRoot(path, false, await lstat(path))).format,
).toBe(extension);
expect(await parseBinaryTarget(path)).toMatchObject({
ok: true,
value: { format: extension },
});
for (let index = 0; index < signature.length; index += 1) {
const changed = Buffer.from(bytes);
changed[offset + index] = changed[offset + index]! | 0x80;
await writeFile(path, changed);
expect(
(await classifyAndHashRoot(path, false, await lstat(path))).format,
).toBe("file");
expect(await parseBinaryTarget(path)).toMatchObject({
ok: false,
error: { _tag: "BinaryTargetError" },
});
}
},
);
});