Pin dependency policy exceptions to versions

This commit is contained in:
2026-08-27 12:51:53 +01:00
parent f28b9ee87d
commit 8098495abf
10 changed files with 125 additions and 27 deletions
+20
View File
@@ -53,6 +53,26 @@ test("check records npm pack size violations without installing", async () => {
assert.equal(report.commands.length, 1);
});
test("check applies an archive override only to its reviewed package version", async () => {
const directory = await makeProject();
const document = packageDocument();
const gitHead = document.versions["1.2.3"].gitHead;
const policy = { ...structuredClone(DEFAULT_POLICY), maxTarballSizeBytes: 10 };
policy.archiveSizeExceptions.alpha = {
version: "1.2.3",
maxTarballSizeBytes: 100,
reason: "Reviewed archive is larger than the default project limit.",
expiresAt: "2025-02-01T00:00:00Z",
};
const report = await checkProject({ path: directory, report: join(directory, "report.json"), policy, skipInstall: true }, {
fetch: async () => jsonResponse(document),
remoteRefs: async () => [{ sha: gitHead, ref: "refs/tags/v1.2.3" }],
run: passingRun(),
now: () => Date.parse("2025-01-01T00:00:00Z"),
});
assert.equal(report.status, "pass");
});
test("check parses full npm pack JSON while truncating report evidence", async () => {
const directory = await makeProject();
const reportPath = join(directory, "report.json");
+10 -2
View File
@@ -19,7 +19,7 @@ test("lock inspection rejects unexpected install scripts and missing integrity",
assert.match(result.failures[1], /integrity/);
});
test("default lock allowlist permits fsevents install script", () => {
test("version-pinned lock exception permits only the reviewed fsevents version", () => {
const lock = {
packages: {
"": {},
@@ -31,5 +31,13 @@ test("default lock allowlist permits fsevents install script", () => {
},
},
};
assert.deepEqual(inspectLock(lock, structuredClone(DEFAULT_POLICY)).failures, []);
const policy = structuredClone(DEFAULT_POLICY);
policy.allowInstallScripts.fsevents = {
versions: ["2.3.3"],
reason: "Reviewed optional native filesystem watcher install script.",
expiresAt: "2027-01-01T00:00:00Z",
};
assert.deepEqual(inspectLock(lock, policy, Date.parse("2026-01-01T00:00:00Z")).failures, []);
lock.packages["node_modules/fsevents"].version = "2.3.4";
assert.match(inspectLock(lock, policy, Date.parse("2026-01-01T00:00:00Z")).failures[0], /2\.3\.4/);
});
+20
View File
@@ -115,6 +115,26 @@ test("rejects direct lifecycle scripts and untrusted maintainers", async () => {
assert.ok(result.failures.some((message) => message.includes("registry maintainer set changed")));
});
test("permits a direct lifecycle script only for the reviewed version", async () => {
const document = packageDocument({ version: { scripts: { postinstall: "node setup.js" } } });
const policy = structuredClone(DEFAULT_POLICY);
policy.allowDirectLifecycleScripts.alpha = {
versions: ["1.2.3"],
reason: "Reviewed package setup script required by this exact release.",
expiresAt: "2025-02-01T00:00:00Z",
};
const dependencies = {
remoteRefs: async () => [{ sha: document.versions["1.2.3"].gitHead, ref: "refs/tags/v1.2.3" }],
now,
timeoutMs: 100,
};
const accepted = await verifyDirectPackage(item, document, policy, dependencies);
assert.ok(!accepted.failures.some((message) => message.includes("lifecycle hook")));
policy.allowDirectLifecycleScripts.alpha.versions = ["1.2.2"];
const rejected = await verifyDirectPackage(item, document, policy, dependencies);
assert.ok(rejected.failures.some((message) => message.includes("lifecycle hook")));
});
test("rejects a missing previously trusted maintainer", async () => {
const document = packageDocument({ version: { maintainers: [{ name: "alice" }] } });
const policy = structuredClone(DEFAULT_POLICY);