Move safe-chain package to packages/safe-chain

This commit is contained in:
Sander Declerck 2025-09-05 11:19:37 +02:00
parent fc9a9ca129
commit 7673d32912
No known key found for this signature in database
68 changed files with 85 additions and 52 deletions

View file

@ -1,92 +0,0 @@
import { auditChanges } from "./audit/index.js";
import { getScanTimeout } from "../config/configFile.js";
import { setTimeout } from "timers/promises";
import chalk from "chalk";
import { getPackageManager } from "../packagemanager/currentPackageManager.js";
import { ui } from "../environment/userInteraction.js";
export function shouldScanCommand(args) {
if (!args || args.length === 0) {
return false;
}
return getPackageManager().isSupportedCommand(args);
}
export async function scanCommand(args) {
if (!shouldScanCommand(args)) {
return [];
}
let timedOut = false;
const spinner = ui.startProcess("Scanning for malicious packages...");
let audit;
await Promise.race([
(async () => {
try {
const packageManager = getPackageManager();
const changes = await packageManager.getDependencyUpdatesForCommand(
args
);
if (timedOut) {
return;
}
if (changes.length > 0) {
spinner.setText(`Scanning ${changes.length} package(s)...`);
}
audit = await auditChanges(changes);
} catch (error) {
spinner.fail(`Error while scanning: ${error.message}`);
throw error;
}
})(),
setTimeout(getScanTimeout()).then(() => {
timedOut = true;
}),
]);
if (timedOut) {
spinner.fail("Timeout exceeded while scanning.");
throw new Error("Timeout exceeded while scanning npm install command.");
}
if (!audit || audit.isAllowed) {
spinner.succeed("No malicious packages detected.");
} else {
printMaliciousChanges(audit.disallowedChanges, spinner);
await acceptRiskOrExit(
"Do you want to continue with the installation despite the risks?",
false
);
}
}
function printMaliciousChanges(changes, spinner) {
spinner.fail(chalk.bold("Malicious changes detected:"));
for (const change of changes) {
ui.writeInformation(` - ${change.name}@${change.version}`);
}
}
async function acceptRiskOrExit(message, defaultValue) {
ui.emptyLine();
const continueInstall = await ui.confirm({
message: message,
default: defaultValue,
});
if (continueInstall) {
ui.writeInformation("Continuing with the installation...");
return;
}
ui.writeInformation("Exiting without installing packages.");
ui.emptyLine();
process.exit(1);
}