npmguard-cli 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/install.js +41 -20
- package/package.json +1 -1
package/dist/commands/install.js
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import ora from "ora";
|
|
3
3
|
import { execSync } from "node:child_process";
|
|
4
|
+
import { writeFile, unlink, mkdir } from "node:fs/promises";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
4
7
|
const IPFS_GATEWAY = "https://gateway.pinata.cloud/ipfs";
|
|
8
|
+
async function downloadFromIPFS(cid, dest) {
|
|
9
|
+
const resp = await fetch(`${IPFS_GATEWAY}/${cid}`);
|
|
10
|
+
if (!resp.ok) {
|
|
11
|
+
throw new Error(`IPFS download failed: ${resp.status}`);
|
|
12
|
+
}
|
|
13
|
+
const buffer = Buffer.from(await resp.arrayBuffer());
|
|
14
|
+
await writeFile(dest, buffer);
|
|
15
|
+
}
|
|
5
16
|
export async function installCommand(packageSpec, auditSource, force = false) {
|
|
6
17
|
const atIndex = packageSpec.lastIndexOf("@");
|
|
7
18
|
let packageName;
|
|
@@ -35,11 +46,11 @@ export async function installCommand(packageSpec, auditSource, force = false) {
|
|
|
35
46
|
console.log();
|
|
36
47
|
console.log(chalk.bold(` ${packageName}@${requestedVersion}`));
|
|
37
48
|
console.log();
|
|
49
|
+
// No audit found — fallback to npm
|
|
38
50
|
if (!audit) {
|
|
39
51
|
console.log(chalk.gray(` NOT AUDITED — no NpmGuard record found for this version.`));
|
|
40
|
-
console.log(chalk.gray(` https://www.npmjs.com/package/${packageName}/v/${requestedVersion}`));
|
|
41
52
|
console.log();
|
|
42
|
-
console.log(chalk.gray("
|
|
53
|
+
console.log(chalk.gray(" Falling back to npm install..."));
|
|
43
54
|
console.log();
|
|
44
55
|
execSync(`npm install ${packageSpec}`, { stdio: "inherit" });
|
|
45
56
|
return;
|
|
@@ -54,36 +65,46 @@ export async function installCommand(packageSpec, auditSource, force = false) {
|
|
|
54
65
|
else if (audit.verdict === "CRITICAL") {
|
|
55
66
|
console.log(chalk.red(` CRITICAL (score: ${audit.score})`));
|
|
56
67
|
}
|
|
57
|
-
// Show capabilities
|
|
58
68
|
if (audit.capabilities.length > 0) {
|
|
59
69
|
console.log(chalk.gray(` Capabilities: ${audit.capabilities.join(", ")}`));
|
|
60
70
|
}
|
|
61
|
-
// Show IPFS links
|
|
62
71
|
if (audit.reportCid) {
|
|
63
72
|
console.log(chalk.gray(` Report: ${IPFS_GATEWAY}/${audit.reportCid}`));
|
|
64
73
|
}
|
|
65
|
-
if (audit.sourceCid) {
|
|
66
|
-
console.log(chalk.gray(` Source: ${IPFS_GATEWAY}/${audit.sourceCid}`));
|
|
67
|
-
}
|
|
68
74
|
console.log();
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
console.log(chalk.yellow(" Installing with warning..."));
|
|
75
|
+
// Block CRITICAL unless --force
|
|
76
|
+
if (audit.verdict === "CRITICAL" && !force) {
|
|
77
|
+
console.log(chalk.red.bold(" Installation blocked. This package has critical security issues."));
|
|
78
|
+
console.log(chalk.gray(" Use --force to install anyway."));
|
|
74
79
|
console.log();
|
|
75
|
-
|
|
80
|
+
return;
|
|
76
81
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
// Install from IPFS if sourceCid is available
|
|
83
|
+
if (audit.sourceCid) {
|
|
84
|
+
const dlSpinner = ora(`Downloading verified source from IPFS (${audit.sourceCid.slice(0, 12)}...)`).start();
|
|
85
|
+
try {
|
|
86
|
+
const tmpDir = join(tmpdir(), "npmguard");
|
|
87
|
+
await mkdir(tmpDir, { recursive: true });
|
|
88
|
+
const tarballPath = join(tmpDir, `${packageName}-${requestedVersion}.tgz`);
|
|
89
|
+
await downloadFromIPFS(audit.sourceCid, tarballPath);
|
|
90
|
+
dlSpinner.succeed("Downloaded from IPFS");
|
|
91
|
+
console.log(chalk.green(` Installing from verified IPFS source...`));
|
|
80
92
|
console.log();
|
|
81
|
-
execSync(`npm install ${
|
|
93
|
+
execSync(`npm install ${tarballPath}`, { stdio: "inherit" });
|
|
94
|
+
// Cleanup
|
|
95
|
+
await unlink(tarballPath).catch(() => { });
|
|
82
96
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
console.log(chalk.
|
|
97
|
+
catch (err) {
|
|
98
|
+
dlSpinner.fail("IPFS download failed");
|
|
99
|
+
console.log(chalk.yellow(" Falling back to npm install..."));
|
|
86
100
|
console.log();
|
|
101
|
+
execSync(`npm install ${packageSpec}`, { stdio: "inherit" });
|
|
87
102
|
}
|
|
88
103
|
}
|
|
104
|
+
else {
|
|
105
|
+
// No sourceCid — install from npm
|
|
106
|
+
console.log(chalk.gray(" No IPFS source available, installing from npm..."));
|
|
107
|
+
console.log();
|
|
108
|
+
execSync(`npm install ${packageSpec}`, { stdio: "inherit" });
|
|
109
|
+
}
|
|
89
110
|
}
|