mirror of
https://github.com/larksuite/cli.git
synced 2026-07-03 14:02:43 +08:00
feat: fail closed when checksums.txt is missing during install (#1503)
This commit is contained in:
@@ -265,10 +265,9 @@ function getExpectedChecksum(archiveName, checksumsDir) {
|
||||
const checksumsPath = path.join(dir, "checksums.txt");
|
||||
|
||||
if (!fs.existsSync(checksumsPath)) {
|
||||
console.error(
|
||||
"[WARN] checksums.txt not found, skipping checksum verification"
|
||||
throw new Error(
|
||||
"[SECURITY] checksums.txt not found; refusing to install an unverified binary."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const content = fs.readFileSync(checksumsPath, "utf8");
|
||||
@@ -286,7 +285,11 @@ function getExpectedChecksum(archiveName, checksumsDir) {
|
||||
}
|
||||
|
||||
function verifyChecksum(archivePath, expectedHash) {
|
||||
if (expectedHash === null) return;
|
||||
if (typeof expectedHash !== "string" || expectedHash.length === 0) {
|
||||
throw new Error(
|
||||
"[SECURITY] missing expected checksum; refusing to install an unverified binary."
|
||||
);
|
||||
}
|
||||
|
||||
// Stream the file to avoid loading the entire archive into memory.
|
||||
// Archives can be 10-100MB; streaming keeps RSS constant.
|
||||
|
||||
@@ -52,11 +52,17 @@ describe("getExpectedChecksum", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("returns null when checksums.txt does not exist", () => {
|
||||
it("throws [SECURITY] when checksums.txt does not exist (fail-closed)", () => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "checksum-test-"));
|
||||
// No checksums.txt in dir
|
||||
const result = getExpectedChecksum("anything.tar.gz", dir);
|
||||
assert.equal(result, null);
|
||||
assert.throws(
|
||||
() => getExpectedChecksum("anything.tar.gz", dir),
|
||||
(err) => {
|
||||
assert.match(err.message, /^\[SECURITY\]/);
|
||||
assert.match(err.message, /checksums\.txt not found/);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("skips malformed lines and still finds valid entry", () => {
|
||||
@@ -125,6 +131,19 @@ describe("verifyChecksum", () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("verifyChecksum throws [SECURITY] on null/empty expectedHash (fail-closed)", () => {
|
||||
const filePath = makeTmpFile("content");
|
||||
for (const expectedHash of [null, ""]) {
|
||||
assert.throws(
|
||||
() => verifyChecksum(filePath, expectedHash),
|
||||
(err) => {
|
||||
assert.match(err.message, /^\[SECURITY\]/);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("assertAllowedHost", () => {
|
||||
|
||||
Reference in New Issue
Block a user