Handle PR Comments

This commit is contained in:
Sander Declerck 2025-10-08 10:49:04 +02:00
parent ea383a18de
commit 240123372a
No known key found for this signature in database
5 changed files with 24 additions and 14 deletions

View file

@ -16,18 +16,20 @@ export async function main(args) {
args = initializeCliArguments(args); args = initializeCliArguments(args);
if (shouldScanCommand(args)) { if (shouldScanCommand(args)) {
const resultCode = await scanCommand(args); const commandScanResult = await scanCommand(args);
// Returning the exit code back to the caller allows the promise // Returning the exit code back to the caller allows the promise
// to be awaited in the bin files and return the correct exit code // to be awaited in the bin files and return the correct exit code
if (resultCode !== 0) { if (commandScanResult !== 0) {
return resultCode; return commandScanResult;
} }
} }
var result = await getPackageManager().runCommand(args); const packageManagerResult = await getPackageManager().runCommand(args);
proxy.verifyNoMaliciousPackages(); if (!proxy.verifyNoMaliciousPackages()) {
return 1;
}
ui.emptyLine(); ui.emptyLine();
ui.writeInformation( ui.writeInformation(
@ -38,7 +40,7 @@ export async function main(args) {
// Returning the exit code back to the caller allows the promise // Returning the exit code back to the caller allows the promise
// to be awaited in the bin files and return the correct exit code // to be awaited in the bin files and return the correct exit code
return result.status; return packageManagerResult.status;
} catch (error) { } catch (error) {
ui.writeError("Failed to check for malicious packages:", error.message); ui.writeError("Failed to check for malicious packages:", error.message);

View file

@ -7,6 +7,7 @@ import { knownRegistries, parsePackageFromUrl } from "./parsePackageFromUrl.js";
import { ui } from "../environment/userInteraction.js"; import { ui } from "../environment/userInteraction.js";
import chalk from "chalk"; import chalk from "chalk";
const SERVER_STOP_TIMEOUT_MS = 1000;
const state = { const state = {
port: null, port: null,
blockedRequests: [], blockedRequests: [],
@ -19,12 +20,15 @@ export function createSafeChainProxy() {
return { return {
startServer: () => startServer(server), startServer: () => startServer(server),
stopServer: () => stopServer(server), stopServer: () => stopServer(server),
getBlockedRequests: () => state.blockedRequests,
verifyNoMaliciousPackages, verifyNoMaliciousPackages,
}; };
} }
function getSafeChainProxyEnvironmentVariables() { function getSafeChainProxyEnvironmentVariables() {
if (!state.port) {
return {};
}
return { return {
HTTPS_PROXY: `http://localhost:${state.port}`, HTTPS_PROXY: `http://localhost:${state.port}`,
GLOBAL_AGENT_HTTP_PROXY: `http://localhost:${state.port}`, GLOBAL_AGENT_HTTP_PROXY: `http://localhost:${state.port}`,
@ -63,6 +67,7 @@ function createProxyServer() {
function startServer(server) { function startServer(server) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Passing port 0 makes the OS assign an available port
server.listen(0, () => { server.listen(0, () => {
const address = server.address(); const address = server.address();
if (address && typeof address === "object") { if (address && typeof address === "object") {
@ -88,7 +93,7 @@ function stopServer(server) {
} catch { } catch {
resolve(); resolve();
} }
setTimeout(() => resolve(), 1000); setTimeout(() => resolve(), SERVER_STOP_TIMEOUT_MS);
}); });
} }
@ -130,7 +135,7 @@ async function isAllowedUrl(url) {
function verifyNoMaliciousPackages() { function verifyNoMaliciousPackages() {
if (state.blockedRequests.length === 0) { if (state.blockedRequests.length === 0) {
// No malicious packages were blocked, so nothing to block // No malicious packages were blocked, so nothing to block
return; return true;
} }
ui.emptyLine(); ui.emptyLine();
@ -149,5 +154,5 @@ function verifyNoMaliciousPackages() {
ui.writeError("Exiting without installing malicious packages."); ui.writeError("Exiting without installing malicious packages.");
ui.emptyLine(); ui.emptyLine();
process.exit(1); return false;
} }

View file

@ -65,8 +65,7 @@ export async function scanCommand(args) {
return 0; return 0;
} else { } else {
printMaliciousChanges(audit.disallowedChanges, spinner); printMaliciousChanges(audit.disallowedChanges, spinner);
await onMalwareFound(); return await onMalwareFound();
return 1;
} }
} }
@ -90,11 +89,11 @@ async function onMalwareFound() {
if (continueInstall) { if (continueInstall) {
ui.writeWarning("Continuing with the installation despite the risks..."); ui.writeWarning("Continuing with the installation despite the risks...");
return; return 0;
} }
} }
ui.writeError("Exiting without installing malicious packages."); ui.writeError("Exiting without installing malicious packages.");
ui.emptyLine(); ui.emptyLine();
process.exit(1); return 1;
} }

View file

@ -31,6 +31,8 @@ export async function openMalwareDatabase() {
return packageData.reason; return packageData.reason;
} }
// This implicitely caches the malware database
// that's closed over by the getPackageStatus function
cachedMalwareDatabase = { cachedMalwareDatabase = {
getPackageStatus, getPackageStatus,
isMalware: (name, version) => { isMalware: (name, version) => {

View file

@ -22,6 +22,8 @@ export async function safeSpawn(command, args, options = {}) {
const fullCommand = buildCommand(command, args); const fullCommand = buildCommand(command, args);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const child = spawn(fullCommand, { ...options, shell: true }); const child = spawn(fullCommand, { ...options, shell: true });
// When stdio is piped, we need to collect the output
let stdout = ""; let stdout = "";
let stderr = ""; let stderr = "";