Files
bun.sh/test/cli/install/bun-update-security-provider.test.ts
Alistair Smith 3ee477fc5b fix: scanner on update, install, remove, uninstall and add, and introduce the pm scan command (#22193)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
2025-09-09 21:42:01 -07:00

151 lines
3.3 KiB
TypeScript

import { afterAll, afterEach, beforeAll, beforeEach, expect, test } from "bun:test";
import { bunEnv, bunExe } from "harness";
import {
dummyAfterAll,
dummyAfterEach,
dummyBeforeAll,
dummyBeforeEach,
dummyRegistry,
package_dir,
setHandler,
write,
} from "./dummy.registry.js";
beforeAll(dummyBeforeAll);
afterAll(dummyAfterAll);
beforeEach(dummyBeforeEach);
afterEach(dummyAfterEach);
test("security scanner blocks bun update on fatal advisory", async () => {
const urls: string[] = [];
setHandler(
dummyRegistry(urls, {
"0.1.0": {},
"0.2.0": {},
}),
);
const scannerCode = `
export const scanner = {
version: "1",
scan: async ({ packages }) => {
if (packages.length === 0) return [];
return [
{
package: "moo",
description: "Fatal security issue detected",
level: "fatal",
url: "https://example.com/critical",
},
];
},
};
`;
await write("./scanner.ts", scannerCode);
await write("package.json", {
name: "my-app",
version: "1.0.0",
dependencies: {
moo: "0.1.0",
},
});
// First install without security scanning (to have something to update)
await using installProc = Bun.spawn({
cmd: [bunExe(), "install", "--no-summary"],
env: bunEnv,
cwd: package_dir,
stdout: "pipe",
stderr: "pipe",
});
await installProc.stdout.text();
await installProc.stderr.text();
await installProc.exited;
await write(
"./bunfig.toml",
`
[install]
saveTextLockfile = false
[install.security]
scanner = "./scanner.ts"
`,
);
await using updateProc = Bun.spawn({
cmd: [bunExe(), "update", "moo"],
env: bunEnv,
cwd: package_dir,
stdout: "pipe",
stderr: "pipe",
});
const [updateOut, updateErr, updateExitCode] = await Promise.all([
updateProc.stdout.text(),
updateProc.stderr.text(),
updateProc.exited,
]);
expect(updateOut).toContain("FATAL: moo");
expect(updateOut).toContain("Fatal security issue detected");
expect(updateOut).toContain("Installation aborted due to fatal security advisories");
expect(updateExitCode).toBe(1);
});
test("security scanner does not run on bun update when disabled", async () => {
const urls: string[] = [];
setHandler(
dummyRegistry(urls, {
"0.1.0": {},
"0.2.0": {},
}),
);
await write("package.json", {
name: "my-app",
version: "1.0.0",
dependencies: {
moo: "0.1.0",
},
});
// Remove bunfig.toml to ensure no security scanner
await write("bunfig.toml", "");
await using installProc = Bun.spawn({
cmd: [bunExe(), "install", "--no-summary"],
env: bunEnv,
cwd: package_dir,
stdout: "pipe",
stderr: "pipe",
});
await installProc.stdout.text();
await installProc.stderr.text();
await installProc.exited;
await using updateProc = Bun.spawn({
cmd: [bunExe(), "update", "moo"],
env: bunEnv,
cwd: package_dir,
stdout: "pipe",
stderr: "pipe",
});
const [updateOut, updateErr, updateExitCode] = await Promise.all([
updateProc.stdout.text(),
updateProc.stderr.text(),
updateProc.exited,
]);
expect(updateOut).not.toContain("Security scanner");
expect(updateOut).not.toContain("WARN:");
expect(updateOut).not.toContain("FATAL:");
expect(updateExitCode).toBe(0);
});