Add pre-install npm dependency guard
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { join } from "node:path";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { checkProject } from "../lib/check.js";
|
||||
import { DEFAULT_POLICY } from "../lib/constants.js";
|
||||
import { jsonResponse, makeProject, packageDocument, passingRun } from "./helpers.js";
|
||||
|
||||
test("check runs only safe npm commands in the required order and writes evidence", async () => {
|
||||
const directory = await makeProject();
|
||||
const reportPath = join(directory, "evidence", "report.json");
|
||||
const calls = [];
|
||||
const document = packageDocument();
|
||||
const gitHead = document.versions["1.2.3"].gitHead;
|
||||
const fetch = async (url) => {
|
||||
if (url.startsWith("https://registry.npmjs.org/alpha")) return jsonResponse(document);
|
||||
throw new Error(`unexpected URL ${url}`);
|
||||
};
|
||||
const report = await checkProject({ path: directory, report: reportPath, policy: structuredClone(DEFAULT_POLICY) }, {
|
||||
fetch,
|
||||
remoteRefs: async () => [{ sha: gitHead, ref: "refs/tags/v1.2.3" }],
|
||||
run: passingRun(calls),
|
||||
now: () => Date.parse("2025-01-01T00:00:00Z"),
|
||||
});
|
||||
assert.equal(report.status, "pass");
|
||||
assert.deepEqual(calls.map((call) => call.slice(0, 3)), [
|
||||
["npm", "pack", "alpha@1.2.3"],
|
||||
["npm", "ci", "--ignore-scripts"],
|
||||
["npm", "audit", "signatures"],
|
||||
["npm", "audit", "--omit=dev"],
|
||||
]);
|
||||
const saved = JSON.parse(await readFile(reportPath, "utf8"));
|
||||
assert.equal(saved.commands.length, 4);
|
||||
assert.equal(saved.status, "pass");
|
||||
});
|
||||
|
||||
test("check records npm pack size violations without installing", async () => {
|
||||
const directory = await makeProject();
|
||||
const reportPath = join(directory, "report.json");
|
||||
const document = packageDocument();
|
||||
const gitHead = document.versions["1.2.3"].gitHead;
|
||||
const report = await checkProject({ path: directory, report: reportPath, policy: { ...structuredClone(DEFAULT_POLICY), maxTarballSizeBytes: 10 }, skipInstall: true }, {
|
||||
fetch: async (url) => {
|
||||
if (url.startsWith("https://registry.npmjs.org/alpha")) return jsonResponse(document);
|
||||
throw new Error(`unexpected URL ${url}`);
|
||||
},
|
||||
remoteRefs: async () => [{ sha: gitHead, ref: "refs/tags/v1.2.3" }],
|
||||
run: passingRun(),
|
||||
now: () => Date.parse("2025-01-01T00:00:00Z"),
|
||||
});
|
||||
assert.equal(report.status, "fail");
|
||||
assert.ok(report.failures.some((message) => message.includes("tarball size")));
|
||||
assert.equal(report.commands.length, 1);
|
||||
});
|
||||
|
||||
test("check parses full npm pack JSON while truncating report evidence", async () => {
|
||||
const directory = await makeProject();
|
||||
const reportPath = join(directory, "report.json");
|
||||
const document = packageDocument();
|
||||
const gitHead = document.versions["1.2.3"].gitHead;
|
||||
const packOutput = JSON.stringify([{
|
||||
size: 100,
|
||||
unpackedSize: 500,
|
||||
files: Array.from({ length: 2_000 }, (_, index) => ({ path: `dist/file-${index}.js`, size: 1 })),
|
||||
}]);
|
||||
assert.ok(packOutput.length > 20_000);
|
||||
|
||||
const report = await checkProject({ path: directory, report: reportPath, policy: structuredClone(DEFAULT_POLICY), skipInstall: true }, {
|
||||
fetch: async (url) => {
|
||||
if (url.startsWith("https://registry.npmjs.org/alpha")) return jsonResponse(document);
|
||||
throw new Error(`unexpected URL ${url}`);
|
||||
},
|
||||
remoteRefs: async () => [{ sha: gitHead, ref: "refs/tags/v1.2.3" }],
|
||||
run: async (_command, _args, options) => {
|
||||
assert.equal(options.maxOutputBytes, 25_000_000);
|
||||
return { code: 0, stdout: packOutput, stderr: "", timedOut: false };
|
||||
},
|
||||
now: () => Date.parse("2025-01-01T00:00:00Z"),
|
||||
});
|
||||
|
||||
assert.equal(report.status, "pass");
|
||||
assert.equal(report.packages[0].tarballSizeBytes, 100);
|
||||
assert.equal(report.commands[0].stdout.length, 20_000);
|
||||
});
|
||||
Reference in New Issue
Block a user