mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 20:20:49 +00:00
Implement a proxy blocking tarball requests for packages containing malware.
This commit is contained in:
parent
04cb001006
commit
e2afcb16e3
16 changed files with 633 additions and 33 deletions
|
|
@ -8,7 +8,8 @@ export function dryRunScanner(scannerOptions) {
|
|||
shouldScan: (args) => shouldScanDependencies(scannerOptions, args),
|
||||
};
|
||||
}
|
||||
function scanDependencies(scannerOptions, args) {
|
||||
|
||||
async function scanDependencies(scannerOptions, args) {
|
||||
let dryRunArgs = args;
|
||||
|
||||
if (scannerOptions?.dryRunCommand) {
|
||||
|
|
@ -31,8 +32,8 @@ function shouldScanDependencies(scannerOptions, args) {
|
|||
return true;
|
||||
}
|
||||
|
||||
function checkChangesWithDryRun(args) {
|
||||
const dryRunOutput = dryRunNpmCommandAndOutput(args);
|
||||
async function checkChangesWithDryRun(args) {
|
||||
const dryRunOutput = await dryRunNpmCommandAndOutput(args);
|
||||
|
||||
// Dry-run can return a non-zero status code in some cases
|
||||
// e.g., when running "npm audit fix --dry-run", it returns exit code 1
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ describe("dryRunScanner", async () => {
|
|||
}));
|
||||
|
||||
const scanner = dryRunScanner();
|
||||
const result = scanner.scan(["audit", "fix"]);
|
||||
const result = await scanner.scan(["audit", "fix"]);
|
||||
|
||||
// Should not throw an error for audit fix commands
|
||||
assert.ok(Array.isArray(result));
|
||||
|
|
@ -53,8 +53,8 @@ describe("dryRunScanner", async () => {
|
|||
|
||||
const scanner = dryRunScanner();
|
||||
|
||||
assert.throws(() => {
|
||||
scanner.scan(["install", "lodash"]);
|
||||
await assert.rejects(async () => {
|
||||
await scanner.scan(["install", "lodash"]);
|
||||
}, /Dry-run command failed with exit code 1/);
|
||||
});
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ describe("dryRunScanner", async () => {
|
|||
}));
|
||||
|
||||
const scanner = dryRunScanner();
|
||||
const result = scanner.scan(["install", "lodash"]);
|
||||
const result = await scanner.scan(["install", "lodash"]);
|
||||
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(mockWriteError.mock.callCount(), 0);
|
||||
|
|
@ -83,8 +83,8 @@ describe("dryRunScanner", async () => {
|
|||
|
||||
const scanner = dryRunScanner();
|
||||
|
||||
assert.throws(() => {
|
||||
scanner.scan(["audit", "fix"]);
|
||||
await assert.rejects(async () => {
|
||||
await scanner.scan(["audit", "fix"]);
|
||||
}, /Dry-run command failed with exit code 1/);
|
||||
});
|
||||
});
|
||||
|
|
@ -99,7 +99,7 @@ describe("dryRunScanner", async () => {
|
|||
}));
|
||||
|
||||
const scanner = dryRunScanner({ dryRunCommand: "install" });
|
||||
scanner.scan(["install-test", "lodash"]);
|
||||
await scanner.scan(["install-test", "lodash"]);
|
||||
|
||||
// Should call with "install" instead of "install-test"
|
||||
assert.equal(mockDryRunNpmCommandAndOutput.mock.callCount(), 1);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
import { execSync } from "child_process";
|
||||
import { ui } from "../../environment/userInteraction.js";
|
||||
import { safeSpawn } from "../../utils/safeSpawn.js";
|
||||
import { mergeSafeChainProxyEnvironmentVariables } from "../../registryProxy/registryProxy.js";
|
||||
|
||||
export function runNpm(args) {
|
||||
export async function runNpm(args) {
|
||||
try {
|
||||
const npmCommand = `npm ${args.join(" ")}`;
|
||||
execSync(npmCommand, { stdio: "inherit" });
|
||||
const result = await safeSpawn("npm", args, {
|
||||
stdio: "inherit",
|
||||
env: mergeSafeChainProxyEnvironmentVariables(process.env),
|
||||
});
|
||||
return { status: result.status };
|
||||
} catch (error) {
|
||||
if (error.status) {
|
||||
return { status: error.status };
|
||||
|
|
@ -13,17 +17,29 @@ export function runNpm(args) {
|
|||
return { status: 1 };
|
||||
}
|
||||
}
|
||||
return { status: 0 };
|
||||
}
|
||||
|
||||
export function dryRunNpmCommandAndOutput(args) {
|
||||
export async function dryRunNpmCommandAndOutput(args) {
|
||||
try {
|
||||
const npmCommand = `npm ${args.join(" ")} --ignore-scripts --dry-run`;
|
||||
const output = execSync(npmCommand, { stdio: "pipe" });
|
||||
return { status: 0, output: output.toString() };
|
||||
const result = await safeSpawn(
|
||||
"npm",
|
||||
[...args, "--ignore-scripts", "--dry-run"],
|
||||
{
|
||||
stdio: "pipe",
|
||||
env: mergeSafeChainProxyEnvironmentVariables(process.env),
|
||||
}
|
||||
);
|
||||
return {
|
||||
status: result.status,
|
||||
output: result.status === 0 ? result.stdout : result.stderr,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error.status) {
|
||||
const output = error.stdout ? error.stdout.toString() : "";
|
||||
const output =
|
||||
error.stdout?.toString() ??
|
||||
error.stderr?.toString() ??
|
||||
error.message ??
|
||||
"";
|
||||
return { status: error.status, output };
|
||||
} else {
|
||||
ui.writeError("Error executing command:", error.message);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue